Add API to support key remappings on native side

For adding support for modifier key remapping, we need to add
native support save key remappings and send appropriate android
key codes using KeyCharacterMap.

Test: atest KeyboardLayoutChangeTest
Bug: 252812993
Change-Id: Ib3efa866c6e6408dd11e97dfaf49feb92f48bc18
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 6d6cefb..b8a6dad 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -88,6 +88,9 @@
     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 f2ea90c..e26bc8c 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -952,15 +952,19 @@
             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 @@
     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 @@
 
         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 150a8aa..e9a94b3 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -624,6 +624,12 @@
     });
 }
 
+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 f04a646..57f679c 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -650,6 +650,15 @@
     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 42ca482..8a844b2 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -262,6 +262,9 @@
 
     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 @@
 
     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 439123b..6fa21e5 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -114,6 +114,8 @@
     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 @@
 
     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 4f2503a..e9c989a 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -68,6 +68,8 @@
     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 f6cf1cc..289a780 100644
--- a/services/inputflinger/tests/FakeEventHub.cpp
+++ b/services/inputflinger/tests/FakeEventHub.cpp
@@ -154,6 +154,11 @@
     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 @@
         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 21cb2f1..fb3c859 100644
--- a/services/inputflinger/tests/FakeEventHub.h
+++ b/services/inputflinger/tests/FakeEventHub.h
@@ -59,6 +59,7 @@
         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 @@
     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 eef5690..4cc48f6 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -2912,6 +2912,27 @@
     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 2eed997..057c15d 100644
--- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
@@ -153,6 +153,10 @@
         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 445ed18..cd852d6 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -211,6 +211,7 @@
     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>();
     }