Add API to get KeyCode produced by physical key location.

The physical key location is provided as a location KeyCode pointing to a location on a US keyboard layout.

Bug: 179812917
Test: atest KeyboardLayoutChangeTest
Test: atest android.hardware.input.cts.tests -m
Test: atest inputflinger_tests -m
Change-Id: Ib5ed41890cbbe393ee9ada1a04cbaaf82c9bb1fc
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 2c5b321..e2596f0 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -439,6 +439,8 @@
         KeyedVector<int32_t, KeyInfo> keysByScanCode;
         KeyedVector<int32_t, KeyInfo> keysByUsageCode;
         KeyedVector<int32_t, bool> leds;
+        // fake mapping which would normally come from keyCharacterMap
+        std::unordered_map<int32_t, int32_t> keyCodeMapping;
         std::unordered_map<int32_t, SensorInfo> sensorsByAbsCode;
         BitArray<MSC_MAX> mscBitmask;
         std::vector<VirtualKeyDefinition> virtualKeys;
@@ -600,6 +602,11 @@
         }
     }
 
+    void addKeyCodeMapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode) {
+        Device* device = getDevice(deviceId);
+        device->keyCodeMapping.insert_or_assign(fromKeyCode, toKeyCode);
+    }
+
     void addLed(int32_t deviceId, int32_t led, bool initialState) {
         Device* device = getDevice(deviceId);
         device->leds.add(led, initialState);
@@ -863,6 +870,15 @@
         return -1;
     }
 
+    int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override {
+        Device* device = getDevice(deviceId);
+        if (!device) {
+            return AKEYCODE_UNKNOWN;
+        }
+        auto it = device->keyCodeMapping.find(locationKeyCode);
+        return it != device->keyCodeMapping.end() ? it->second : locationKeyCode;
+    }
+
     // Return true if the device has non-empty key layout.
     bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
                                uint8_t* outFlags) const override {
@@ -1034,6 +1050,8 @@
     KeyedVector<int32_t, int32_t> mKeyCodeStates;
     KeyedVector<int32_t, int32_t> mScanCodeStates;
     KeyedVector<int32_t, int32_t> mSwitchStates;
+    // fake mapping which would normally come from keyCharacterMap
+    std::unordered_map<int32_t, int32_t> mKeyCodeMapping;
     std::vector<int32_t> mSupportedKeyCodes;
 
     std::mutex mLock;
@@ -1122,8 +1140,12 @@
         mSupportedKeyCodes.push_back(keyCode);
     }
 
+    void addKeyCodeMapping(int32_t fromKeyCode, int32_t toKeyCode) {
+        mKeyCodeMapping.insert_or_assign(fromKeyCode, toKeyCode);
+    }
+
 private:
-    uint32_t getSources() override { return mSources; }
+    uint32_t getSources() const override { return mSources; }
 
     void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {
         InputMapper::populateDeviceInfo(deviceInfo);
@@ -1164,6 +1186,11 @@
         return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
     }
 
+    int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override {
+        auto it = mKeyCodeMapping.find(locationKeyCode);
+        return it != mKeyCodeMapping.end() ? it->second : locationKeyCode;
+    }
+
     int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
         ssize_t index = mScanCodeStates.indexOfKey(scanCode);
         return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
@@ -1712,6 +1739,37 @@
             << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
 }
 
+TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_ForwardsRequestsToMappers) {
+    constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+    constexpr int32_t eventHubId = 1;
+    FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "keyboard",
+                                                           InputDeviceClass::KEYBOARD,
+                                                           AINPUT_SOURCE_KEYBOARD, nullptr);
+    mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
+
+    ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(0, AKEYCODE_Y))
+            << "Should return unknown when the device with the specified id is not found.";
+
+    ASSERT_EQ(AKEYCODE_Z, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
+            << "Should return correct mapping when device id is valid and mapping exists.";
+
+    ASSERT_EQ(AKEYCODE_A, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_A))
+            << "Should return the location key code when device id is valid and there's no "
+               "mapping.";
+}
+
+TEST_F(InputReaderTest, GetKeyCodeForKeyLocation_NoKeyboardMapper) {
+    constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+    constexpr int32_t eventHubId = 1;
+    FakeInputMapper& mapper = addDeviceWithFakeInputMapper(deviceId, eventHubId, "joystick",
+                                                           InputDeviceClass::JOYSTICK,
+                                                           AINPUT_SOURCE_GAMEPAD, nullptr);
+    mapper.addKeyCodeMapping(AKEYCODE_Y, AKEYCODE_Z);
+
+    ASSERT_EQ(AKEYCODE_UNKNOWN, mReader->getKeyCodeForKeyLocation(deviceId, AKEYCODE_Y))
+            << "Should return unknown when the device id is valid but there is no keyboard mapper";
+}
+
 TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
     constexpr int32_t deviceId = END_RESERVED_ID + 1000;
     constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
@@ -3609,6 +3667,19 @@
     ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
 }
 
+TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
+    KeyboardInputMapper& mapper =
+            addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
+                                                       AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+
+    mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
+    ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
+            << "If a mapping is available, the result is equal to the mapping";
+
+    ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
+            << "If no mapping is available, the result is the key location";
+}
+
 TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
     KeyboardInputMapper& mapper =
             addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,