summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/input/KeyCharacterMap.h20
-rw-r--r--libs/input/KeyCharacterMap.cpp150
-rw-r--r--services/inputflinger/include/InputReaderBase.h3
-rw-r--r--services/inputflinger/reader/EventHub.cpp30
-rw-r--r--services/inputflinger/reader/InputDevice.cpp6
-rw-r--r--services/inputflinger/reader/InputReader.cpp9
-rw-r--r--services/inputflinger/reader/include/EventHub.h6
-rw-r--r--services/inputflinger/reader/include/InputDevice.h6
-rw-r--r--services/inputflinger/reader/include/InputReader.h2
-rw-r--r--services/inputflinger/tests/FakeEventHub.cpp8
-rw-r--r--services/inputflinger/tests/FakeEventHub.h2
-rw-r--r--services/inputflinger/tests/InputReader_test.cpp21
-rw-r--r--services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp4
-rw-r--r--services/inputflinger/tests/fuzzers/MapperHelpers.h1
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>();
}