Propagate MotionClassification to InputDispatcher

We added MotionClassification to MotionEvent and NotifyMotionArgs, but
the two have not yet been connected. Connect them here, to ensure that
apps can receive the classification.

Bug: 111480215
Test: atest -a libinput_tests inputflinger_tests
Change-Id: I67dda22d9ee8a2d89abf40dbd01200ec37a65737
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index db86c8e..9fd25f9 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -29,6 +29,17 @@
 
 namespace android {
 
+const char* motionClassificationToString(MotionClassification classification) {
+    switch (classification) {
+        case MotionClassification::NONE:
+            return "NONE";
+        case MotionClassification::AMBIGUOUS_GESTURE:
+            return "AMBIGUOUS_GESTURE";
+        case MotionClassification::DEEP_PRESS:
+            return "DEEP_PRESS";
+    }
+}
+
 // --- InputEvent ---
 
 void InputEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId) {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 0ddee44..0f7a1f0 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -157,6 +157,8 @@
             msg->body.motion.metaState = body.motion.metaState;
             // int32_t buttonState
             msg->body.motion.buttonState = body.motion.buttonState;
+            // MotionClassification classification
+            msg->body.motion.classification = body.motion.classification;
             // int32_t edgeFlags
             msg->body.motion.edgeFlags = body.motion.edgeFlags;
             // nsecs_t downTime
@@ -448,6 +450,7 @@
         int32_t edgeFlags,
         int32_t metaState,
         int32_t buttonState,
+        MotionClassification classification,
         float xOffset,
         float yOffset,
         float xPrecision,
@@ -461,13 +464,13 @@
     ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
             "displayId=%" PRId32 ", "
             "action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
-            "metaState=0x%x, buttonState=0x%x, xOffset=%f, yOffset=%f, "
+            "metaState=0x%x, buttonState=0x%x, classification=%s, xOffset=%f, yOffset=%f, "
             "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", "
             "pointerCount=%" PRIu32,
             mChannel->getName().c_str(), seq,
             deviceId, source, displayId, action, actionButton, flags, edgeFlags, metaState,
-            buttonState, xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime,
-            pointerCount);
+            buttonState, motionClassificationToString(classification),
+            xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
 #endif
 
     if (!seq) {
@@ -493,6 +496,7 @@
     msg.body.motion.edgeFlags = edgeFlags;
     msg.body.motion.metaState = metaState;
     msg.body.motion.buttonState = buttonState;
+    msg.body.motion.classification = classification;
     msg.body.motion.xOffset = xOffset;
     msg.body.motion.yOffset = yOffset;
     msg.body.motion.xPrecision = xPrecision;
@@ -1112,7 +1116,7 @@
             msg->body.motion.edgeFlags,
             msg->body.motion.metaState,
             msg->body.motion.buttonState,
-            MotionClassification::NONE,
+            msg->body.motion.classification,
             msg->body.motion.xOffset,
             msg->body.motion.yOffset,
             msg->body.motion.xPrecision,
diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp
index 96c165c..f1675c0 100644
--- a/libs/input/tests/InputChannel_test.cpp
+++ b/libs/input/tests/InputChannel_test.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <array>
+
 #include "TestHelpers.h"
 
 #include <unistd.h>
@@ -155,5 +157,37 @@
             << "sendMessage should have returned DEAD_OBJECT";
 }
 
+TEST_F(InputChannelTest, SendAndReceive_MotionClassification) {
+    sp<InputChannel> serverChannel, clientChannel;
+    status_t result = InputChannel::openInputChannelPair("channel name",
+            serverChannel, clientChannel);
+    ASSERT_EQ(OK, result)
+            << "should have successfully opened a channel pair";
+
+    std::array<MotionClassification, 3> classifications = {
+        MotionClassification::NONE,
+        MotionClassification::AMBIGUOUS_GESTURE,
+        MotionClassification::DEEP_PRESS,
+    };
+
+    InputMessage serverMsg = {}, clientMsg;
+    serverMsg.header.type = InputMessage::TYPE_MOTION;
+    serverMsg.body.motion.seq = 1;
+    serverMsg.body.motion.pointerCount = 1;
+
+    for (MotionClassification classification : classifications) {
+        // Send and receive a message with classification
+        serverMsg.body.motion.classification = classification;
+        EXPECT_EQ(OK, serverChannel->sendMessage(&serverMsg))
+                << "server channel should be able to send message to client channel";
+
+        EXPECT_EQ(OK, clientChannel->receiveMessage(&clientMsg))
+                << "client channel should be able to receive message from server channel";
+        EXPECT_EQ(serverMsg.header.type, clientMsg.header.type);
+        EXPECT_EQ(classification, clientMsg.body.motion.classification) <<
+                "Expected to receive " << motionClassificationToString(classification);
+    }
+}
+
 
 } // namespace android
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index e4c1514..2b75c82 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <array>
 #include <math.h>
 
 #include <binder/Parcel.h>
@@ -25,11 +26,7 @@
 // Default display id.
 static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
 
-class BaseTest : public testing::Test {
-protected:
-    virtual void SetUp() { }
-    virtual void TearDown() { }
-};
+class BaseTest : public testing::Test { };
 
 // --- PointerCoordsTest ---
 
@@ -316,6 +313,7 @@
     ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
     ASSERT_EQ(AMETA_ALT_ON, event->getMetaState());
     ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState());
+    ASSERT_EQ(MotionClassification::NONE, event->getClassification());
     ASSERT_EQ(X_OFFSET, event->getXOffset());
     ASSERT_EQ(Y_OFFSET, event->getYOffset());
     ASSERT_EQ(2.0f, event->getXPrecision());
@@ -609,4 +607,30 @@
     ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
 }
 
+TEST_F(MotionEventTest, Initialize_SetsClassification) {
+    std::array<MotionClassification, 3> classifications = {
+            MotionClassification::NONE,
+            MotionClassification::AMBIGUOUS_GESTURE,
+            MotionClassification::DEEP_PRESS,
+    };
+
+    MotionEvent event;
+    constexpr size_t pointerCount = 1;
+    PointerProperties pointerProperties[pointerCount];
+    PointerCoords pointerCoords[pointerCount];
+    for (size_t i = 0; i < pointerCount; i++) {
+        pointerProperties[i].clear();
+        pointerProperties[i].id = i;
+        pointerCoords[i].clear();
+    }
+
+    for (MotionClassification classification : classifications) {
+        event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+                AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0,
+                classification, 0, 0, 0, 0, 0 /*downTime*/, 0 /*eventTime*/,
+                pointerCount, pointerProperties, pointerCoords);
+        ASSERT_EQ(classification, event.getClassification());
+    }
+}
+
 } // namespace android
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 0788c89..f2cd1be 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -141,6 +141,7 @@
     constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
     constexpr int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
     constexpr int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY;
+    constexpr MotionClassification classification = MotionClassification::AMBIGUOUS_GESTURE;
     constexpr float xOffset = -10;
     constexpr float yOffset = -20;
     constexpr float xPrecision = 0.25;
@@ -168,8 +169,8 @@
     }
 
     status = mPublisher->publishMotionEvent(seq, deviceId, source, displayId, action, actionButton,
-            flags, edgeFlags, metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision,
-            downTime, eventTime, pointerCount,
+            flags, edgeFlags, metaState, buttonState, classification,
+            xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount,
             pointerProperties, pointerCoords);
     ASSERT_EQ(OK, status)
             << "publisher publishMotionEvent should return OK";
@@ -195,6 +196,7 @@
     EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
     EXPECT_EQ(metaState, motionEvent->getMetaState());
     EXPECT_EQ(buttonState, motionEvent->getButtonState());
+    EXPECT_EQ(classification, motionEvent->getClassification());
     EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
     EXPECT_EQ(yPrecision, motionEvent->getYPrecision());
     EXPECT_EQ(downTime, motionEvent->getDownTime());
@@ -264,7 +266,8 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
@@ -276,7 +279,8 @@
     PointerProperties pointerProperties[pointerCount];
     PointerCoords pointerCoords[pointerCount];
 
-    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
@@ -293,7 +297,8 @@
         pointerCoords[i].clear();
     }
 
-    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            MotionClassification::NONE, 0, 0, 0, 0, 0, 0,
             pointerCount, pointerProperties, pointerCoords);
     ASSERT_EQ(BAD_VALUE, status)
             << "publisher publishMotionEvent should return BAD_VALUE";
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 12a6782..62023fb 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -57,7 +57,8 @@
   CHECK_OFFSET(InputMessage::Body::Motion, flags, 36);
   CHECK_OFFSET(InputMessage::Body::Motion, metaState, 40);
   CHECK_OFFSET(InputMessage::Body::Motion, buttonState, 44);
-  CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 48);
+  CHECK_OFFSET(InputMessage::Body::Motion, classification, 48);
+  CHECK_OFFSET(InputMessage::Body::Motion, edgeFlags, 52);
   CHECK_OFFSET(InputMessage::Body::Motion, downTime, 56);
   CHECK_OFFSET(InputMessage::Body::Motion, xOffset, 64);
   CHECK_OFFSET(InputMessage::Body::Motion, yOffset, 68);