Use identity transform for Joystick MotionEvent

The SyntheticJoystickHandler makes key events
according to the axis values of MotionEvent.

If there is a Window which has transformed,
the axis values are going to be bigger or smaller than
SyntheticJoystickHandler's threshold and the generating
events never stop because JoystickHandler thinks that
the user is controlling Joystick continuously.

This makes Joystick's MotionEvent has identity transform
so that its aix values are not depending on the window but
display.

Test: atest inputflinger_tests:InputDispatcherTest\
        #NonPointerMotionEvent_JoystickNotTransformed
Bug: 158802274
Change-Id: Ib1c12c773a604c74807033819b8d1e1032913c98
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 5832109..dcac786 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -321,6 +321,17 @@
 static std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget,
                                                           std::shared_ptr<EventEntry> eventEntry,
                                                           int32_t inputTargetFlags) {
+    if (eventEntry->type == EventEntry::Type::MOTION) {
+        const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry);
+        if (motionEntry.source & AINPUT_SOURCE_CLASS_JOYSTICK) {
+            const ui::Transform identityTransform;
+            // Use identity transform for joystick events events because they don't depend on
+            // the window info
+            return std::make_unique<DispatchEntry>(eventEntry, inputTargetFlags, identityTransform,
+                                                   1.0f /*globalScaleFactor*/);
+        }
+    }
+
     if (inputTarget.useDefaultPointerTransform()) {
         const ui::Transform& transform = inputTarget.getDefaultPointerTransform();
         return std::make_unique<DispatchEntry>(eventEntry, inputTargetFlags, transform,
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 0b30ff5..9d8a1bb 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -862,6 +862,8 @@
 
     void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
 
+    void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
+
     void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
         consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
                      expectedFlags);
@@ -2051,6 +2053,50 @@
     EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
 }
 
+TEST_F(InputDispatcherTest, NonPointerMotionEvent_JoystickNotTransformed) {
+    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+    sp<FakeWindowHandle> window =
+            new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
+    const std::string name = window->getName();
+
+    // Window gets transformed by offset values.
+    window->setWindowOffset(500.0f, 500.0f);
+
+    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+    window->setFocusable(true);
+
+    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
+
+    // First, we set focused window so that focusedWindowHandle is not null.
+    setFocusedWindow(window);
+
+    // Second, we consume focus event if it is right or wrong according to onFocusChangedLocked.
+    window->consumeFocusEvent(true);
+
+    NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
+                                                     AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_DEFAULT);
+    mDispatcher->notifyMotion(&motionArgs);
+
+    // Third, we consume motion event.
+    InputEvent* event = window->consume();
+    ASSERT_NE(event, nullptr);
+    ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
+            << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
+            << " event, got " << inputEventTypeToString(event->getType()) << " event";
+
+    const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
+    EXPECT_EQ(AINPUT_EVENT_TYPE_MOTION, motionEvent.getAction());
+
+    float expectedX = motionArgs.pointerCoords[0].getX();
+    float expectedY = motionArgs.pointerCoords[0].getY();
+
+    // Finally we test if the axis values from the final motion event are not transformed
+    EXPECT_EQ(expectedX, motionEvent.getX(0)) << "expected " << expectedX << " for x coord of "
+                                              << name.c_str() << ", got " << motionEvent.getX(0);
+    EXPECT_EQ(expectedY, motionEvent.getY(0)) << "expected " << expectedY << " for y coord of "
+                                              << name.c_str() << ", got " << motionEvent.getY(0);
+}
+
 /**
  * Ensure that separate calls to sign the same data are generating the same key.
  * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance