Add FocusEvent and InputMessage::Type::FOCUS

FocusEvents will be consumed by InputConsumer on the app side. They
will be used to notify app that focus has been gained / lost. They will
also carry information about the current state of touch mode.

Also add a new type of InputMessage with type FOCUS.
This new data structure will be used to pass focus events to the apps
from input across the socket.

Bug: 70668286
Test: presubmit
Change-Id: I88582c64ee41ecb49623b9b7f5c149eafa694788
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index c7303ef..8ccbc7f 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -20,6 +20,7 @@
 #include <limits.h>
 
 #include <input/Input.h>
+#include <input/InputDevice.h>
 #include <input/InputEventLabels.h>
 
 #ifdef __ANDROID__
@@ -41,6 +42,21 @@
 
 // --- InputEvent ---
 
+const char* inputEventTypeToString(int32_t type) {
+    switch (type) {
+        case AINPUT_EVENT_TYPE_KEY: {
+            return "KEY";
+        }
+        case AINPUT_EVENT_TYPE_MOTION: {
+            return "MOTION";
+        }
+        case AINPUT_EVENT_TYPE_FOCUS: {
+            return "FOCUS";
+        }
+    }
+    return "UNKNOWN";
+}
+
 void InputEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId) {
     mDeviceId = deviceId;
     mSource = source;
@@ -587,6 +603,20 @@
     return getAxisByLabel(label);
 }
 
+// --- FocusEvent ---
+
+void FocusEvent::initialize(bool hasFocus, bool inTouchMode) {
+    InputEvent::initialize(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN,
+                           ADISPLAY_ID_NONE);
+    mHasFocus = hasFocus;
+    mInTouchMode = inTouchMode;
+}
+
+void FocusEvent::initialize(const FocusEvent& from) {
+    InputEvent::initialize(from);
+    mHasFocus = from.mHasFocus;
+    mInTouchMode = from.mInTouchMode;
+}
 
 // --- PooledInputEventFactory ---
 
@@ -615,6 +645,15 @@
     return event;
 }
 
+FocusEvent* PooledInputEventFactory::createFocusEvent() {
+    if (mFocusEventPool.empty()) {
+        return new FocusEvent();
+    }
+    FocusEvent* event = mFocusEventPool.front().release();
+    mFocusEventPool.pop();
+    return event;
+}
+
 void PooledInputEventFactory::recycle(InputEvent* event) {
     switch (event->getType()) {
     case AINPUT_EVENT_TYPE_KEY:
@@ -629,6 +668,12 @@
             return;
         }
         break;
+    case AINPUT_EVENT_TYPE_FOCUS:
+        if (mFocusEventPool.size() < mMaxPoolSize) {
+            mFocusEventPool.push(std::unique_ptr<FocusEvent>(static_cast<FocusEvent*>(event)));
+            return;
+        }
+        break;
     }
     delete event;
 }