diff options
-rw-r--r-- | include/input/KeyCharacterMap.h | 20 | ||||
-rw-r--r-- | libs/input/KeyCharacterMap.cpp | 150 | ||||
-rw-r--r-- | services/inputflinger/include/InputReaderBase.h | 3 | ||||
-rw-r--r-- | services/inputflinger/reader/EventHub.cpp | 30 | ||||
-rw-r--r-- | services/inputflinger/reader/InputDevice.cpp | 6 | ||||
-rw-r--r-- | services/inputflinger/reader/InputReader.cpp | 9 | ||||
-rw-r--r-- | services/inputflinger/reader/include/EventHub.h | 6 | ||||
-rw-r--r-- | services/inputflinger/reader/include/InputDevice.h | 6 | ||||
-rw-r--r-- | services/inputflinger/reader/include/InputReader.h | 2 | ||||
-rw-r--r-- | services/inputflinger/tests/FakeEventHub.cpp | 8 | ||||
-rw-r--r-- | services/inputflinger/tests/FakeEventHub.h | 2 | ||||
-rw-r--r-- | services/inputflinger/tests/InputReader_test.cpp | 21 | ||||
-rw-r--r-- | services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp | 4 | ||||
-rw-r--r-- | services/inputflinger/tests/fuzzers/MapperHelpers.h | 1 |
14 files changed, 198 insertions, 70 deletions
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index dc928b806f..867a08955c 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -125,14 +125,21 @@ public: bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars, Vector<KeyEvent>& outEvents) const; + /* Maps an Android key code to another Android key code. This mapping is applied after scanCode + * and usageCodes are mapped to corresponding Android Keycode */ + void addKeyRemapping(int32_t fromKeyCode, int32_t toKeyCode); + /* Maps a scan code and usage code to a key code, in case this key map overrides * the mapping in some way. */ status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const; - /* Tries to find a replacement key code for a given key code and meta state - * in character map. */ - void tryRemapKey(int32_t scanCode, int32_t metaState, - int32_t* outKeyCode, int32_t* outMetaState) const; + /* Returns keycode after applying Android key code remapping defined in mKeyRemapping */ + int32_t applyKeyRemapping(int32_t fromKeyCode) const; + + /* Returns the <keyCode, metaState> pair after applying key behavior defined in the kcm file, + * that tries to find a replacement key code based on current meta state */ + std::pair<int32_t /*keyCode*/, int32_t /*metaState*/> applyKeyBehavior(int32_t keyCode, + int32_t metaState) const; #ifdef __linux__ /* Reads a key map from a parcel. */ @@ -227,8 +234,9 @@ private: std::string mLoadFileName; bool mLayoutOverlayApplied; - KeyedVector<int32_t, int32_t> mKeysByScanCode; - KeyedVector<int32_t, int32_t> mKeysByUsageCode; + std::map<int32_t /* fromAndroidKeyCode */, int32_t /* toAndroidKeyCode */> mKeyRemapping; + std::map<int32_t /* fromScanCode */, int32_t /* toAndroidKeyCode */> mKeysByScanCode; + std::map<int32_t /* fromHidUsageCode */, int32_t /* toAndroidKeyCode */> mKeysByUsageCode; KeyCharacterMap(const std::string& filename); diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index 422e6e09eb..fa5c41f657 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -43,7 +43,6 @@ // Enables debug output for mapping. #define DEBUG_MAPPING 0 - namespace android { static const char* WHITESPACE = " \t\r"; @@ -93,6 +92,7 @@ KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other) : mType(other.mType), mLoadFileName(other.mLoadFileName), mLayoutOverlayApplied(other.mLayoutOverlayApplied), + mKeyRemapping(other.mKeyRemapping), mKeysByScanCode(other.mKeysByScanCode), mKeysByUsageCode(other.mKeysByUsageCode) { for (size_t i = 0; i < other.mKeys.size(); i++) { @@ -114,7 +114,7 @@ bool KeyCharacterMap::operator==(const KeyCharacterMap& other) const { if (mLayoutOverlayApplied != other.mLayoutOverlayApplied) { return false; } - if (mKeys.size() != other.mKeys.size() || + if (mKeys.size() != other.mKeys.size() || mKeyRemapping.size() != other.mKeyRemapping.size() || mKeysByScanCode.size() != other.mKeysByScanCode.size() || mKeysByUsageCode.size() != other.mKeysByUsageCode.size()) { return false; @@ -131,22 +131,9 @@ bool KeyCharacterMap::operator==(const KeyCharacterMap& other) const { } } - 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; - } + if (mKeyRemapping != other.mKeyRemapping || mKeysByScanCode != other.mKeysByScanCode || + mKeysByUsageCode != other.mKeysByUsageCode) { + return false; } return true; @@ -258,14 +245,12 @@ void KeyCharacterMap::combine(const KeyCharacterMap& overlay) { } } - for (size_t i = 0; i < overlay.mKeysByScanCode.size(); i++) { - mKeysByScanCode.replaceValueFor(overlay.mKeysByScanCode.keyAt(i), - overlay.mKeysByScanCode.valueAt(i)); + for (auto const& it : overlay.mKeysByScanCode) { + mKeysByScanCode.insert_or_assign(it.first, it.second); } - for (size_t i = 0; i < overlay.mKeysByUsageCode.size(); i++) { - mKeysByUsageCode.replaceValueFor(overlay.mKeysByUsageCode.keyAt(i), - overlay.mKeysByUsageCode.valueAt(i)); + for (auto const& it : overlay.mKeysByUsageCode) { + mKeysByUsageCode.insert_or_assign(it.first, it.second); } mLayoutOverlayApplied = true; } @@ -400,11 +385,26 @@ bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t return true; } +void KeyCharacterMap::addKeyRemapping(int32_t fromKeyCode, int32_t toKeyCode) { + if (fromKeyCode == toKeyCode) { + mKeyRemapping.erase(fromKeyCode); +#if DEBUG_MAPPING + ALOGD("addKeyRemapping: Cleared remapping forKeyCode=%d ~ Result Successful.", fromKeyCode); +#endif + return; + } + mKeyRemapping.insert_or_assign(fromKeyCode, toKeyCode); +#if DEBUG_MAPPING + ALOGD("addKeyRemapping: fromKeyCode=%d, toKeyCode=%d ~ Result Successful.", fromKeyCode, + toKeyCode); +#endif +} + status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const { if (usageCode) { - ssize_t index = mKeysByUsageCode.indexOfKey(usageCode); - if (index >= 0) { - *outKeyCode = mKeysByUsageCode.valueAt(index); + const auto it = mKeysByUsageCode.find(usageCode); + if (it != mKeysByUsageCode.end()) { + *outKeyCode = it->second; #if DEBUG_MAPPING ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.", scanCode, usageCode, *outKeyCode); @@ -413,9 +413,9 @@ status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* o } } if (scanCode) { - ssize_t index = mKeysByScanCode.indexOfKey(scanCode); - if (index >= 0) { - *outKeyCode = mKeysByScanCode.valueAt(index); + const auto it = mKeysByScanCode.find(scanCode); + if (it != mKeysByScanCode.end()) { + *outKeyCode = it->second; #if DEBUG_MAPPING ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.", scanCode, usageCode, *outKeyCode); @@ -431,45 +431,59 @@ status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* o return NAME_NOT_FOUND; } -void KeyCharacterMap::tryRemapKey(int32_t keyCode, int32_t metaState, - int32_t *outKeyCode, int32_t *outMetaState) const { - *outKeyCode = keyCode; - *outMetaState = metaState; +int32_t KeyCharacterMap::applyKeyRemapping(int32_t fromKeyCode) const { + int32_t toKeyCode = fromKeyCode; - const Behavior* behavior = getKeyBehavior(keyCode, metaState); + const auto it = mKeyRemapping.find(fromKeyCode); + if (it != mKeyRemapping.end()) { + toKeyCode = it->second; + } +#if DEBUG_MAPPING + ALOGD("applyKeyRemapping: keyCode=%d ~ replacement keyCode=%d.", fromKeyCode, toKeyCode); +#endif + return toKeyCode; +} + +std::pair<int32_t, int32_t> KeyCharacterMap::applyKeyBehavior(int32_t fromKeyCode, + int32_t fromMetaState) const { + int32_t toKeyCode = fromKeyCode; + int32_t toMetaState = fromMetaState; + + const Behavior* behavior = getKeyBehavior(fromKeyCode, fromMetaState); if (behavior != nullptr) { if (behavior->replacementKeyCode) { - *outKeyCode = behavior->replacementKeyCode; - int32_t newMetaState = metaState & ~behavior->metaState; + toKeyCode = behavior->replacementKeyCode; + toMetaState = fromMetaState & ~behavior->metaState; // Reset dependent meta states. if (behavior->metaState & AMETA_ALT_ON) { - newMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON); + toMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON); } if (behavior->metaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) { - newMetaState &= ~AMETA_ALT_ON; + toMetaState &= ~AMETA_ALT_ON; } if (behavior->metaState & AMETA_CTRL_ON) { - newMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON); + toMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON); } if (behavior->metaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) { - newMetaState &= ~AMETA_CTRL_ON; + toMetaState &= ~AMETA_CTRL_ON; } if (behavior->metaState & AMETA_SHIFT_ON) { - newMetaState &= ~(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON); + toMetaState &= ~(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON); } if (behavior->metaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) { - newMetaState &= ~AMETA_SHIFT_ON; + toMetaState &= ~AMETA_SHIFT_ON; } // ... and put universal bits back if needed - *outMetaState = normalizeMetaState(newMetaState); + toMetaState = normalizeMetaState(toMetaState); } } #if DEBUG_MAPPING - ALOGD("tryRemapKey: keyCode=%d, metaState=0x%08x ~ " - "replacement keyCode=%d, replacement metaState=0x%08x.", - keyCode, metaState, *outKeyCode, *outMetaState); + ALOGD("applyKeyBehavior: keyCode=%d, metaState=0x%08x ~ " + "replacement keyCode=%d, replacement metaState=0x%08x.", + fromKeyCode, fromMetaState, toKeyCode, toMetaState); #endif + return std::make_pair(toKeyCode, toMetaState); } bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const { @@ -720,6 +734,18 @@ std::shared_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) return nullptr; } } + size_t numKeyRemapping = parcel->readInt32(); + if (parcel->errorCheck()) { + return nullptr; + } + for (size_t i = 0; i < numKeyRemapping; i++) { + int32_t key = parcel->readInt32(); + int32_t value = parcel->readInt32(); + map->mKeyRemapping.insert_or_assign(key, value); + if (parcel->errorCheck()) { + return nullptr; + } + } size_t numKeysByScanCode = parcel->readInt32(); if (parcel->errorCheck()) { return nullptr; @@ -727,7 +753,7 @@ std::shared_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) for (size_t i = 0; i < numKeysByScanCode; i++) { int32_t key = parcel->readInt32(); int32_t value = parcel->readInt32(); - map->mKeysByScanCode.add(key, value); + map->mKeysByScanCode.insert_or_assign(key, value); if (parcel->errorCheck()) { return nullptr; } @@ -739,7 +765,7 @@ std::shared_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) for (size_t i = 0; i < numKeysByUsageCode; i++) { int32_t key = parcel->readInt32(); int32_t value = parcel->readInt32(); - map->mKeysByUsageCode.add(key, value); + map->mKeysByUsageCode.insert_or_assign(key, value); if (parcel->errorCheck()) { return nullptr; } @@ -773,17 +799,23 @@ void KeyCharacterMap::writeToParcel(Parcel* parcel) const { } parcel->writeInt32(0); } + size_t numKeyRemapping = mKeyRemapping.size(); + parcel->writeInt32(numKeyRemapping); + for (auto const& [fromAndroidKeyCode, toAndroidKeyCode] : mKeyRemapping) { + parcel->writeInt32(fromAndroidKeyCode); + parcel->writeInt32(toAndroidKeyCode); + } size_t numKeysByScanCode = mKeysByScanCode.size(); parcel->writeInt32(numKeysByScanCode); - for (size_t i = 0; i < numKeysByScanCode; i++) { - parcel->writeInt32(mKeysByScanCode.keyAt(i)); - parcel->writeInt32(mKeysByScanCode.valueAt(i)); + for (auto const& [fromScanCode, toAndroidKeyCode] : mKeysByScanCode) { + parcel->writeInt32(fromScanCode); + parcel->writeInt32(toAndroidKeyCode); } size_t numKeysByUsageCode = mKeysByUsageCode.size(); parcel->writeInt32(numKeysByUsageCode); - for (size_t i = 0; i < numKeysByUsageCode; i++) { - parcel->writeInt32(mKeysByUsageCode.keyAt(i)); - parcel->writeInt32(mKeysByUsageCode.valueAt(i)); + for (auto const& [fromUsageCode, toAndroidKeyCode] : mKeysByUsageCode) { + parcel->writeInt32(fromUsageCode); + parcel->writeInt32(toAndroidKeyCode); } } #endif // __linux__ @@ -950,9 +982,9 @@ status_t KeyCharacterMap::Parser::parseMapKey() { mapUsage ? "usage" : "scan code", codeToken.string()); return BAD_VALUE; } - KeyedVector<int32_t, int32_t>& map = - mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; - if (map.indexOfKey(code) >= 0) { + std::map<int32_t, int32_t>& map = mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode; + const auto it = map.find(code); + if (it != map.end()) { ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(), mapUsage ? "usage" : "scan code", codeToken.string()); return BAD_VALUE; @@ -971,7 +1003,7 @@ status_t KeyCharacterMap::Parser::parseMapKey() { ALOGD("Parsed map key %s: code=%d, keyCode=%d.", mapUsage ? "usage" : "scan code", code, keyCode); #endif - map.add(code, keyCode); + map.insert_or_assign(code, keyCode); return NO_ERROR; } diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 6d6cefb0c0..b8a6dade34 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -88,6 +88,9 @@ public: virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw) = 0; + virtual void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, + int32_t toKeyCode) const = 0; + virtual int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const = 0; /* Toggle Caps Lock */ diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index f2ea90c291..e26bc8c6dc 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -952,15 +952,19 @@ int32_t EventHub::getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKey device->getKeyCharacterMap()->mapKey(scanCodes[0], 0 /*usageCode*/, &outKeyCode); switch (mapKeyRes) { case OK: - return outKeyCode; + break; case NAME_NOT_FOUND: // key character map doesn't re-map this scanCode, hence the keyCode remains the same - return locationKeyCode; + outKeyCode = locationKeyCode; + break; default: ALOGW("Failed to get key code for key location: Key character map returned error %s", statusToString(mapKeyRes).c_str()); - return AKEYCODE_UNKNOWN; + outKeyCode = AKEYCODE_UNKNOWN; + break; } + // Remap if there is a Key remapping added to the KCM and return the remapped key + return device->getKeyCharacterMap()->applyKeyRemapping(outKeyCode); } int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const { @@ -1023,6 +1027,18 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t return false; } +void EventHub::addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode) const { + std::scoped_lock _l(mLock); + Device* device = getDeviceLocked(deviceId); + if (device == nullptr) { + return; + } + const std::shared_ptr<KeyCharacterMap> kcm = device->getKeyCharacterMap(); + if (kcm) { + kcm->addKeyRemapping(fromKeyCode, toKeyCode); + } +} + status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const { std::scoped_lock _l(mLock); @@ -1048,7 +1064,13 @@ status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, if (status == NO_ERROR) { if (kcm) { - kcm->tryRemapKey(*outKeycode, metaState, outKeycode, outMetaState); + // Remap keys based on user-defined key remappings and key behavior defined in the + // corresponding kcm file + *outKeycode = kcm->applyKeyRemapping(*outKeycode); + + // Remap keys based on Key behavior defined in KCM file + std::tie(*outKeycode, *outMetaState) = + kcm->applyKeyBehavior(*outKeycode, metaState); } else { *outMetaState = metaState; } diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 150a8aac0d..e9a94b3a42 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -624,6 +624,12 @@ void InputDevice::updateMetaState(int32_t keyCode) { }); } +void InputDevice::addKeyRemapping(int32_t fromKeyCode, int32_t toKeyCode) { + for_each_subdevice([fromKeyCode, toKeyCode](auto& context) { + context.addKeyRemapping(fromKeyCode, toKeyCode); + }); +} + void InputDevice::bumpGeneration() { mGeneration = mContext->bumpGeneration(); } diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index f04a6469ea..57f679c022 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -650,6 +650,15 @@ bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceM return result; } +void InputReader::addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode) const { + std::scoped_lock _l(mLock); + + InputDevice* device = findInputDeviceLocked(deviceId); + if (device != nullptr) { + device->addKeyRemapping(fromKeyCode, toKeyCode); + } +} + int32_t InputReader::getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const { std::scoped_lock _l(mLock); diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 42ca482a68..8a844b2088 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -262,6 +262,9 @@ public: virtual bool hasMscEvent(int32_t deviceId, int mscEvent) const = 0; + virtual void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, + int32_t toKeyCode) 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; @@ -460,6 +463,9 @@ public: bool hasMscEvent(int32_t deviceId, int mscEvent) const override final; + void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, + int32_t toKeyCode) 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; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 439123bf1d..6fa21e5362 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -114,6 +114,8 @@ public: int32_t getMetaState(); void updateMetaState(int32_t keyCode); + void addKeyRemapping(int32_t fromKeyCode, int32_t toKeyCode); + void bumpGeneration(); [[nodiscard]] NotifyDeviceResetArgs notifyReset(nsecs_t when); @@ -278,6 +280,10 @@ public: inline bool hasMscEvent(int mscEvent) const { return mEventHub->hasMscEvent(mId, mscEvent); } + inline void addKeyRemapping(int32_t fromKeyCode, int32_t toKeyCode) const { + mEventHub->addKeyRemapping(mId, fromKeyCode, toKeyCode); + } + 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, diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index 4f2503ad5c..e9c989a224 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -68,6 +68,8 @@ public: int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode) override; int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw) override; + void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode) const override; + int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override; void toggleCapsLockState(int32_t deviceId) override; diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp index f6cf1cc304..289a7809cc 100644 --- a/services/inputflinger/tests/FakeEventHub.cpp +++ b/services/inputflinger/tests/FakeEventHub.cpp @@ -154,6 +154,11 @@ void FakeEventHub::addKeyCodeMapping(int32_t deviceId, int32_t fromKeyCode, int3 getDevice(deviceId)->keyCodeMapping.insert_or_assign(fromKeyCode, toKeyCode); } +void FakeEventHub::addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode) const { + Device* device = getDevice(deviceId); + device->keyRemapping.insert_or_assign(fromKeyCode, toKeyCode); +} + void FakeEventHub::addLed(int32_t deviceId, int32_t led, bool initialState) { getDevice(deviceId)->leds.add(led, initialState); } @@ -299,7 +304,8 @@ status_t FakeEventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageC const KeyInfo* key = getKey(device, scanCode, usageCode); if (key) { if (outKeycode) { - *outKeycode = key->keyCode; + auto it = device->keyRemapping.find(key->keyCode); + *outKeycode = it != device->keyRemapping.end() ? it->second : key->keyCode; } if (outFlags) { *outFlags = key->flags; diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h index 21cb2f1963..fb3c8596c7 100644 --- a/services/inputflinger/tests/FakeEventHub.h +++ b/services/inputflinger/tests/FakeEventHub.h @@ -59,6 +59,7 @@ class FakeEventHub : public EventHubInterface { KeyedVector<int32_t, int32_t> absoluteAxisValue; KeyedVector<int32_t, KeyInfo> keysByScanCode; KeyedVector<int32_t, KeyInfo> keysByUsageCode; + std::unordered_map<int32_t, int32_t> keyRemapping; KeyedVector<int32_t, bool> leds; // fake mapping which would normally come from keyCharacterMap std::unordered_map<int32_t, int32_t> keyCodeMapping; @@ -132,6 +133,7 @@ public: void addKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t keyCode, uint32_t flags); void addKeyCodeMapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode); + void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode) const; void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition); void addSensorAxis(int32_t deviceId, int32_t absCode, InputDeviceSensorType sensorType, diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index eef56902c7..4cc48f6fc3 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -2912,6 +2912,27 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { ASSERT_EQ(ARBITRARY_TIME, args.downTime); } +TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) { + mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0); + mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0); + mFakeEventHub->addKeyRemapping(EVENTHUB_ID, AKEYCODE_A, AKEYCODE_B); + + KeyboardInputMapper& mapper = + addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD, + AINPUT_KEYBOARD_TYPE_ALPHABETIC); + + // Key down by scan code. + process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1); + NotifyKeyArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(AKEYCODE_B, args.keyCode); + + // Key up by scan code. + process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(AKEYCODE_B, args.keyCode); +} + /** * Ensure that the readTime is set to the time when the EV_KEY is received. */ diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp index 2eed9977be..057c15d6b8 100644 --- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp @@ -153,6 +153,10 @@ public: return reader->getLightPlayerId(deviceId, lightId); } + void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode) const { + reader->addKeyRemapping(deviceId, fromKeyCode, toKeyCode); + } + int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const { return reader->getKeyCodeForKeyLocation(deviceId, locationKeyCode); } diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index 445ed182fe..cd852d668c 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -211,6 +211,7 @@ public: int32_t getSwitchState(int32_t deviceId, int32_t sw) const override { return mFdp->ConsumeIntegral<int32_t>(); } + void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode) const override {} int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override { return mFdp->ConsumeIntegral<int32_t>(); } |