InputDispatcher: Notify policy of focus changes.

The java InputManagerService layer needs to know of focus changes
as it tracks pointer capture. However the source of truth for focus
is now the native side.

Bug: 80101428
Bug: 113136004
Bug: 111440400
Change-Id: If7a96548926b4ccce12ccd01d1dc336b45254a54
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 49aac72..93a8ac0 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -3126,6 +3126,11 @@
 #endif
                 mFocusedWindowHandlesByDisplay[displayId] = newFocusedWindowHandle;
             }
+
+            if (mFocusedDisplayId == displayId) {
+                onFocusChangedLocked(newFocusedWindowHandle);
+            }
+
         }
 
         ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
@@ -3241,6 +3246,8 @@
             // Sanity check
             sp<InputWindowHandle> newFocusedWindowHandle =
                     getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
+            onFocusChangedLocked(newFocusedWindowHandle);
+
             if (newFocusedWindowHandle == nullptr) {
                 ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
                 if (!mFocusedWindowHandlesByDisplay.empty()) {
@@ -3799,6 +3806,13 @@
     commandEntry->connection = connection;
 }
 
+void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& newFocus) {
+    sp<IBinder> token = newFocus != nullptr ? newFocus->getToken() : nullptr;
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doNotifyFocusChangedLockedInterruptible);
+    commandEntry->token = token;
+}
+
 void InputDispatcher::onANRLocked(
         nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
         const sp<InputWindowHandle>& windowHandle,
@@ -3856,6 +3870,14 @@
     }
 }
 
+void InputDispatcher::doNotifyFocusChangedLockedInterruptible(
+        CommandEntry* commandEntry) {
+    sp<IBinder> token = commandEntry->token;
+    mLock.unlock();
+    mPolicy->notifyFocusChanged(token);
+    mLock.lock();
+}
+
 void InputDispatcher::doNotifyANRLockedInterruptible(
         CommandEntry* commandEntry) {
     mLock.unlock();
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 9ecabdb..11df5d9 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -214,6 +214,7 @@
 
     /* Notifies the system that an input channel is unrecoverably broken. */
     virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
+    virtual void notifyFocusChanged(const sp<IBinder>& token) = 0;
 
     /* Gets the input dispatcher configuration. */
     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
@@ -623,6 +624,7 @@
         uint32_t seq;
         bool handled;
         sp<InputChannel> inputChannel;
+        sp<IBinder> token;
     };
 
     // Generic queue implementation.
@@ -1152,6 +1154,7 @@
             nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled);
     void onDispatchCycleBrokenLocked(
             nsecs_t currentTime, const sp<Connection>& connection);
+    void onFocusChangedLocked(const sp<InputWindowHandle>& newFocus);
     void onANRLocked(
             nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
             const sp<InputWindowHandle>& windowHandle,
@@ -1160,6 +1163,7 @@
     // Outbound policy interactions.
     void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry);
     void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
+    void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry);
     void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);
     void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
     void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry);