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/InputTransport.cpp b/libs/input/InputTransport.cpp
index b7937dc..200e1f3 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -103,6 +103,8 @@
                 return body.motion.pointerCount > 0 && body.motion.pointerCount <= MAX_POINTERS;
             case Type::FINISHED:
                 return true;
+            case Type::FOCUS:
+                return true;
         }
     }
     return false;
@@ -116,6 +118,8 @@
             return sizeof(Header) + body.motion.size();
         case Type::FINISHED:
             return sizeof(Header) + body.finished.size();
+        case Type::FOCUS:
+            return sizeof(Header) + body.focus.size();
     }
     return sizeof(Header);
 }
@@ -220,6 +224,12 @@
             msg->body.finished.handled = body.finished.handled;
             break;
         }
+        case InputMessage::Type::FOCUS: {
+            msg->body.focus.seq = body.focus.seq;
+            msg->body.focus.hasFocus = body.focus.hasFocus;
+            msg->body.focus.inTouchMode = body.focus.inTouchMode;
+            break;
+        }
     }
 }
 
@@ -529,6 +539,23 @@
     return mChannel->sendMessage(&msg);
 }
 
+status_t InputPublisher::publishFocusEvent(uint32_t seq, bool hasFocus, bool inTouchMode) {
+    if (ATRACE_ENABLED()) {
+        std::string message =
+                StringPrintf("publishFocusEvent(inputChannel=%s, hasFocus=%s, inTouchMode=%s)",
+                             mChannel->getName().c_str(), toString(hasFocus),
+                             toString(inTouchMode));
+        ATRACE_NAME(message.c_str());
+    }
+
+    InputMessage msg;
+    msg.header.type = InputMessage::Type::FOCUS;
+    msg.body.focus.seq = seq;
+    msg.body.focus.hasFocus = hasFocus ? 1 : 0;
+    msg.body.focus.inTouchMode = inTouchMode ? 1 : 0;
+    return mChannel->sendMessage(&msg);
+}
+
 status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) {
     if (DEBUG_TRANSPORT_ACTIONS) {
         ALOGD("channel '%s' publisher ~ receiveFinishedSignal", mChannel->getName().c_str());
@@ -565,8 +592,8 @@
     return property_get_bool(PROPERTY_RESAMPLING_ENABLED, true);
 }
 
-status_t InputConsumer::consume(InputEventFactoryInterface* factory,
-        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
+status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consumeBatches,
+                                nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
     if (DEBUG_TRANSPORT_ACTIONS) {
         ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64,
               mChannel->getName().c_str(), toString(consumeBatches), frameTime);
@@ -669,19 +696,19 @@
                     break;
                 }
 
-            MotionEvent* motionEvent = factory->createMotionEvent();
-            if (! motionEvent) return NO_MEMORY;
+                MotionEvent* motionEvent = factory->createMotionEvent();
+                if (!motionEvent) return NO_MEMORY;
 
-            updateTouchState(mMsg);
-            initializeMotionEvent(motionEvent, &mMsg);
-            *outSeq = mMsg.body.motion.seq;
-            *outEvent = motionEvent;
+                updateTouchState(mMsg);
+                initializeMotionEvent(motionEvent, &mMsg);
+                *outSeq = mMsg.body.motion.seq;
+                *outEvent = motionEvent;
 
-            if (DEBUG_TRANSPORT_ACTIONS) {
-                ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u",
-                      mChannel->getName().c_str(), *outSeq);
-            }
-            break;
+                if (DEBUG_TRANSPORT_ACTIONS) {
+                    ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u",
+                          mChannel->getName().c_str(), *outSeq);
+                }
+                break;
             }
 
             case InputMessage::Type::FINISHED: {
@@ -689,6 +716,16 @@
                                  "InputConsumer!");
                 break;
             }
+
+            case InputMessage::Type::FOCUS: {
+                FocusEvent* focusEvent = factory->createFocusEvent();
+                if (!focusEvent) return NO_MEMORY;
+
+                initializeFocusEvent(focusEvent, &mMsg);
+                *outSeq = mMsg.body.focus.seq;
+                *outEvent = focusEvent;
+                break;
+            }
         }
     }
     return OK;
@@ -1113,6 +1150,10 @@
             msg->body.key.eventTime);
 }
 
+void InputConsumer::initializeFocusEvent(FocusEvent* event, const InputMessage* msg) {
+    event->initialize(msg->body.focus.hasFocus == 1, msg->body.focus.inTouchMode == 1);
+}
+
 void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage* msg) {
     uint32_t pointerCount = msg->body.motion.pointerCount;
     PointerProperties pointerProperties[pointerCount];