Loading include/input/Input.h +10 −0 Original line number Original line Diff line number Diff line Loading @@ -285,6 +285,16 @@ enum { // This policy flag prevents key events from changing touch mode state. // This policy flag prevents key events from changing touch mode state. POLICY_FLAG_GESTURE = 0x00000008, POLICY_FLAG_GESTURE = 0x00000008, // Indicates that key usage mapping represents a fallback mapping. // Fallback mappings cannot be used to definitively determine whether a device // supports a key code. For example, a HID device can report a key press // as a HID usage code if it is not mapped to any linux key code in the kernel. // However, we cannot know which HID usage codes that device supports from // userspace through the evdev. We can use fallback mappings to convert HID // usage codes to Android key codes without needing to know if a device can // actually report the usage code. POLICY_FLAG_FALLBACK_USAGE_MAPPING = 0x00000010, POLICY_FLAG_RAW_MASK = 0x0000ffff, POLICY_FLAG_RAW_MASK = 0x0000ffff, #ifdef __linux__ #ifdef __linux__ Loading libs/input/InputEventLabels.cpp +2 −1 Original line number Original line Diff line number Diff line Loading @@ -430,7 +430,8 @@ namespace android { DEFINE_FLAG(VIRTUAL), \ DEFINE_FLAG(VIRTUAL), \ DEFINE_FLAG(FUNCTION), \ DEFINE_FLAG(FUNCTION), \ DEFINE_FLAG(GESTURE), \ DEFINE_FLAG(GESTURE), \ DEFINE_FLAG(WAKE) DEFINE_FLAG(WAKE), \ DEFINE_FLAG(FALLBACK_USAGE_MAPPING) // clang-format on // clang-format on Loading libs/input/KeyLayoutMap.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -250,7 +250,7 @@ std::vector<int32_t> KeyLayoutMap::findScanCodesForKey(int32_t keyCode) const { std::vector<int32_t> KeyLayoutMap::findUsageCodesForKey(int32_t keyCode) const { std::vector<int32_t> KeyLayoutMap::findUsageCodesForKey(int32_t keyCode) const { std::vector<int32_t> usageCodes; std::vector<int32_t> usageCodes; for (const auto& [usageCode, key] : mKeysByUsageCode) { for (const auto& [usageCode, key] : mKeysByUsageCode) { if (keyCode == key.keyCode) { if (keyCode == key.keyCode && !(key.flags & POLICY_FLAG_FALLBACK_USAGE_MAPPING)) { usageCodes.push_back(usageCode); usageCodes.push_back(usageCode); } } } } Loading libs/input/tests/InputDevice_test.cpp +35 −0 Original line number Original line Diff line number Diff line Loading @@ -167,6 +167,41 @@ TEST_F(InputDeviceKeyMapTest, keyCharacterMapBadLedLabel) { ASSERT_FALSE(ret.ok()) << "Should not be able to load KeyLayout at " << klPath; ASSERT_FALSE(ret.ok()) << "Should not be able to load KeyLayout at " << klPath; } } TEST(InputDeviceKeyLayoutTest, HidUsageCodesFallbackMapping) { std::string klPath = base::GetExecutableDirectory() + "/data/hid_fallback_mapping.kl"; base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(klPath); ASSERT_TRUE(ret.ok()) << "Unable to load KeyLayout at " << klPath; const std::shared_ptr<KeyLayoutMap>& keyLayoutMap = *ret; static constexpr std::array<int32_t, 5> hidUsageCodesWithoutFallback = {0x0c0067, 0x0c0070, 0x0c006F, 0x0c0079, 0x0c007A}; for (int32_t hidUsageCode : hidUsageCodesWithoutFallback) { int32_t outKeyCode; uint32_t outFlags; keyLayoutMap->mapKey(0, hidUsageCode, &outKeyCode, &outFlags); ASSERT_FALSE(outFlags & POLICY_FLAG_FALLBACK_USAGE_MAPPING) << "HID usage code should not be marked as fallback"; std::vector<int32_t> usageCodes = keyLayoutMap->findUsageCodesForKey(outKeyCode); ASSERT_NE(std::find(usageCodes.begin(), usageCodes.end(), hidUsageCode), usageCodes.end()) << "Fallback usage code should be mapped to key"; } static constexpr std::array<int32_t, 6> hidUsageCodesWithFallback = {0x0c007C, 0x0c0173, 0x0c019C, 0x0c01A2, 0x0d0044, 0x0d005a}; for (int32_t hidUsageCode : hidUsageCodesWithFallback) { int32_t outKeyCode; uint32_t outFlags; keyLayoutMap->mapKey(0, hidUsageCode, &outKeyCode, &outFlags); ASSERT_TRUE(outFlags & POLICY_FLAG_FALLBACK_USAGE_MAPPING) << "HID usage code should be marked as fallback"; std::vector<int32_t> usageCodes = keyLayoutMap->findUsageCodesForKey(outKeyCode); ASSERT_EQ(std::find(usageCodes.begin(), usageCodes.end(), hidUsageCode), usageCodes.end()) << "Fallback usage code should not be mapped to key"; } } TEST(InputDeviceKeyLayoutTest, DoesNotLoadWhenRequiredKernelConfigIsMissing) { TEST(InputDeviceKeyLayoutTest, DoesNotLoadWhenRequiredKernelConfigIsMissing) { #if !defined(__ANDROID__) #if !defined(__ANDROID__) GTEST_SKIP() << "Can't check kernel configs on host"; GTEST_SKIP() << "Can't check kernel configs on host"; Loading libs/input/tests/data/hid_fallback_mapping.kl 0 → 100644 +32 −0 Original line number Original line Diff line number Diff line # Copyright 2023 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # test key layout file for InputDeviceKeyMapTest#HidUsageCodesUseFallbackMapping # # Keys defined by HID usages without fallback mapping flag key usage 0x0c0067 WINDOW key usage 0x0c006F BRIGHTNESS_UP key usage 0x0c0070 BRIGHTNESS_DOWN key usage 0x0c0079 KEYBOARD_BACKLIGHT_UP key usage 0x0c007A KEYBOARD_BACKLIGHT_DOWN # Keys defined by HID usages with fallback mapping flag key usage 0x0c007C KEYBOARD_BACKLIGHT_TOGGLE FALLBACK_USAGE_MAPPING key usage 0x0c0173 MEDIA_AUDIO_TRACK FALLBACK_USAGE_MAPPING key usage 0x0c019C PROFILE_SWITCH FALLBACK_USAGE_MAPPING key usage 0x0c01A2 ALL_APPS FALLBACK_USAGE_MAPPING key usage 0x0d0044 STYLUS_BUTTON_PRIMARY FALLBACK_USAGE_MAPPING key usage 0x0d005a STYLUS_BUTTON_SECONDARY FALLBACK_USAGE_MAPPING No newline at end of file Loading
include/input/Input.h +10 −0 Original line number Original line Diff line number Diff line Loading @@ -285,6 +285,16 @@ enum { // This policy flag prevents key events from changing touch mode state. // This policy flag prevents key events from changing touch mode state. POLICY_FLAG_GESTURE = 0x00000008, POLICY_FLAG_GESTURE = 0x00000008, // Indicates that key usage mapping represents a fallback mapping. // Fallback mappings cannot be used to definitively determine whether a device // supports a key code. For example, a HID device can report a key press // as a HID usage code if it is not mapped to any linux key code in the kernel. // However, we cannot know which HID usage codes that device supports from // userspace through the evdev. We can use fallback mappings to convert HID // usage codes to Android key codes without needing to know if a device can // actually report the usage code. POLICY_FLAG_FALLBACK_USAGE_MAPPING = 0x00000010, POLICY_FLAG_RAW_MASK = 0x0000ffff, POLICY_FLAG_RAW_MASK = 0x0000ffff, #ifdef __linux__ #ifdef __linux__ Loading
libs/input/InputEventLabels.cpp +2 −1 Original line number Original line Diff line number Diff line Loading @@ -430,7 +430,8 @@ namespace android { DEFINE_FLAG(VIRTUAL), \ DEFINE_FLAG(VIRTUAL), \ DEFINE_FLAG(FUNCTION), \ DEFINE_FLAG(FUNCTION), \ DEFINE_FLAG(GESTURE), \ DEFINE_FLAG(GESTURE), \ DEFINE_FLAG(WAKE) DEFINE_FLAG(WAKE), \ DEFINE_FLAG(FALLBACK_USAGE_MAPPING) // clang-format on // clang-format on Loading
libs/input/KeyLayoutMap.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -250,7 +250,7 @@ std::vector<int32_t> KeyLayoutMap::findScanCodesForKey(int32_t keyCode) const { std::vector<int32_t> KeyLayoutMap::findUsageCodesForKey(int32_t keyCode) const { std::vector<int32_t> KeyLayoutMap::findUsageCodesForKey(int32_t keyCode) const { std::vector<int32_t> usageCodes; std::vector<int32_t> usageCodes; for (const auto& [usageCode, key] : mKeysByUsageCode) { for (const auto& [usageCode, key] : mKeysByUsageCode) { if (keyCode == key.keyCode) { if (keyCode == key.keyCode && !(key.flags & POLICY_FLAG_FALLBACK_USAGE_MAPPING)) { usageCodes.push_back(usageCode); usageCodes.push_back(usageCode); } } } } Loading
libs/input/tests/InputDevice_test.cpp +35 −0 Original line number Original line Diff line number Diff line Loading @@ -167,6 +167,41 @@ TEST_F(InputDeviceKeyMapTest, keyCharacterMapBadLedLabel) { ASSERT_FALSE(ret.ok()) << "Should not be able to load KeyLayout at " << klPath; ASSERT_FALSE(ret.ok()) << "Should not be able to load KeyLayout at " << klPath; } } TEST(InputDeviceKeyLayoutTest, HidUsageCodesFallbackMapping) { std::string klPath = base::GetExecutableDirectory() + "/data/hid_fallback_mapping.kl"; base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(klPath); ASSERT_TRUE(ret.ok()) << "Unable to load KeyLayout at " << klPath; const std::shared_ptr<KeyLayoutMap>& keyLayoutMap = *ret; static constexpr std::array<int32_t, 5> hidUsageCodesWithoutFallback = {0x0c0067, 0x0c0070, 0x0c006F, 0x0c0079, 0x0c007A}; for (int32_t hidUsageCode : hidUsageCodesWithoutFallback) { int32_t outKeyCode; uint32_t outFlags; keyLayoutMap->mapKey(0, hidUsageCode, &outKeyCode, &outFlags); ASSERT_FALSE(outFlags & POLICY_FLAG_FALLBACK_USAGE_MAPPING) << "HID usage code should not be marked as fallback"; std::vector<int32_t> usageCodes = keyLayoutMap->findUsageCodesForKey(outKeyCode); ASSERT_NE(std::find(usageCodes.begin(), usageCodes.end(), hidUsageCode), usageCodes.end()) << "Fallback usage code should be mapped to key"; } static constexpr std::array<int32_t, 6> hidUsageCodesWithFallback = {0x0c007C, 0x0c0173, 0x0c019C, 0x0c01A2, 0x0d0044, 0x0d005a}; for (int32_t hidUsageCode : hidUsageCodesWithFallback) { int32_t outKeyCode; uint32_t outFlags; keyLayoutMap->mapKey(0, hidUsageCode, &outKeyCode, &outFlags); ASSERT_TRUE(outFlags & POLICY_FLAG_FALLBACK_USAGE_MAPPING) << "HID usage code should be marked as fallback"; std::vector<int32_t> usageCodes = keyLayoutMap->findUsageCodesForKey(outKeyCode); ASSERT_EQ(std::find(usageCodes.begin(), usageCodes.end(), hidUsageCode), usageCodes.end()) << "Fallback usage code should not be mapped to key"; } } TEST(InputDeviceKeyLayoutTest, DoesNotLoadWhenRequiredKernelConfigIsMissing) { TEST(InputDeviceKeyLayoutTest, DoesNotLoadWhenRequiredKernelConfigIsMissing) { #if !defined(__ANDROID__) #if !defined(__ANDROID__) GTEST_SKIP() << "Can't check kernel configs on host"; GTEST_SKIP() << "Can't check kernel configs on host"; Loading
libs/input/tests/data/hid_fallback_mapping.kl 0 → 100644 +32 −0 Original line number Original line Diff line number Diff line # Copyright 2023 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # test key layout file for InputDeviceKeyMapTest#HidUsageCodesUseFallbackMapping # # Keys defined by HID usages without fallback mapping flag key usage 0x0c0067 WINDOW key usage 0x0c006F BRIGHTNESS_UP key usage 0x0c0070 BRIGHTNESS_DOWN key usage 0x0c0079 KEYBOARD_BACKLIGHT_UP key usage 0x0c007A KEYBOARD_BACKLIGHT_DOWN # Keys defined by HID usages with fallback mapping flag key usage 0x0c007C KEYBOARD_BACKLIGHT_TOGGLE FALLBACK_USAGE_MAPPING key usage 0x0c0173 MEDIA_AUDIO_TRACK FALLBACK_USAGE_MAPPING key usage 0x0c019C PROFILE_SWITCH FALLBACK_USAGE_MAPPING key usage 0x0c01A2 ALL_APPS FALLBACK_USAGE_MAPPING key usage 0x0d0044 STYLUS_BUTTON_PRIMARY FALLBACK_USAGE_MAPPING key usage 0x0d005a STYLUS_BUTTON_SECONDARY FALLBACK_USAGE_MAPPING No newline at end of file