Merge "Force input device changed callback when Keyboard layout info is updated" into udc-dev
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 66d3435..1a40fdb 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -212,6 +212,11 @@
     std::string languageTag;
     // The layout type such as QWERTY or AZERTY.
     std::string layoutType;
+
+    inline bool operator==(const KeyboardLayoutInfo& other) const {
+        return languageTag == other.languageTag && layoutType == other.layoutType;
+    }
+    inline bool operator!=(const KeyboardLayoutInfo& other) const { return !(*this == other); }
 };
 
 // The version of the Universal Stylus Initiative (USI) protocol supported by the input device.
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 582fb46..7388752 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -148,8 +148,12 @@
 
     if (!changes.any() ||
         changes.test(InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION)) {
-        mKeyboardLayoutInfo =
+        std::optional<KeyboardLayoutInfo> newKeyboardLayoutInfo =
                 getValueByKey(config.keyboardLayoutAssociations, getDeviceContext().getLocation());
+        if (mKeyboardLayoutInfo != newKeyboardLayoutInfo) {
+            mKeyboardLayoutInfo = newKeyboardLayoutInfo;
+            bumpGeneration();
+        }
     }
 
     return out;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 0b50504..d56db11 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -3687,6 +3687,7 @@
             mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
                                /*changes=*/{});
 
+    uint32_t generation = mReader->getContext()->getGeneration();
     mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
 
     unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
@@ -3697,6 +3698,14 @@
               deviceInfo.getKeyboardLayoutInfo()->languageTag);
     ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
               deviceInfo.getKeyboardLayoutInfo()->layoutType);
+    ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
+
+    // Call change layout association with the same values: Generation shouldn't change
+    generation = mReader->getContext()->getGeneration();
+    mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
+    unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+                                 InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
+    ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
 }
 
 TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {