InputDispatcher: Track InputChannels by IBinder token.

In the context of passing input through SurfaceFlinger we need
to change the way InputWindowHandles are passed back to the WindowManager.
In the past the InputDispatcher and the WindowManager have been in the same process.
This is taken advantange of by having the InputDispatcher pass back the same object
to the WindowManager (say in interceptKeyBeforeQueueing) which was passed in from
the WindowManager originally (in setInputWindows) this means if the WindowManager
needs to assosciate a WindowState with a given InputWindowHandle it could just
piggy back some information on a subclass of the object and cast it when receiving back
from the Input subsystem. Since the objects will be parcelled across IPC boundaries now
and the WM will not be the caller of setInputWindows, this mechanism won't work. Instead we
ask the WindowManager to provide an IBinder token at registration time, which we can parcel
through the process as a UUID. We provide this token back to Policy callbacks to enable
the WindowManager to look up it's local state.

Bug: 80101428
Bug: 113136004
Bug: 111440400
Test: Manual
Change-Id: Ia828eb61082240f38d82f89e04956da108f636de
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 4c91427..d906db3 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -31,6 +31,7 @@
 
 #include <string>
 
+#include <binder/IBinder.h>
 #include <input/Input.h>
 #include <utils/Errors.h>
 #include <utils/Timers.h>
@@ -190,11 +191,16 @@
     status_t write(Parcel& out) const;
     status_t read(const Parcel& from);
 
+    sp<IBinder> getToken() const;
+    void setToken(const sp<IBinder>& token);
+
 private:
     void setFd(int fd);
 
     std::string mName;
     int mFd = -1;
+
+    sp<IBinder> mToken = nullptr;
 };
 
 /*
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 32444f9..e93f3a4 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -247,6 +247,10 @@
     if (s != OK) {
         return s;
     }
+    s = out.writeStrongBinder(mToken);
+    if (s != OK) {
+        return s;
+    }
 
     s = out.writeDupFileDescriptor(getFd());
 
@@ -255,6 +259,7 @@
 
 status_t InputChannel::read(const Parcel& from) {
     mName = from.readString8();
+    mToken = from.readStrongBinder();
 
     int rawFd = from.readFileDescriptor();
     setFd(::dup(rawFd));
@@ -266,6 +271,17 @@
     return OK;
 }
 
+sp<IBinder> InputChannel::getToken() const {
+    return mToken;
+}
+
+void InputChannel::setToken(const sp<IBinder>& token) {
+    if (mToken != nullptr) {
+        ALOGE("Assigning InputChannel (%s) a second handle?", mName.c_str());
+    }
+    mToken = token;
+}
+
 // --- InputPublisher ---
 
 InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 3f39afd..b57510a 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -818,7 +818,7 @@
             sp<InputWindowHandle> focusedWindowHandle =
                     getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(entry));
             if (focusedWindowHandle != nullptr) {
-                commandEntry->inputWindowHandle = focusedWindowHandle;
+                commandEntry->inputChannel = focusedWindowHandle->getInputChannel();
             }
             commandEntry->keyEntry = entry;
             entry->refCount += 1;
@@ -1064,6 +1064,13 @@
     }
 }
 
+void InputDispatcher::removeWindowByTokenLocked(const sp<IBinder>& token) {
+    for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
+        TouchState& state = mTouchStatesByDisplay.editValueAt(d);
+        state.removeWindowByToken(token);
+    }
+}
+
 void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
         const sp<InputChannel>& inputChannel) {
     if (newTimeout > 0) {
@@ -1078,17 +1085,10 @@
             ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
             if (connectionIndex >= 0) {
                 sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
-                sp<InputWindowHandle> windowHandle = connection->inputWindowHandle;
+                sp<IBinder> token = connection->inputChannel->getToken();
 
-                if (windowHandle != nullptr) {
-                    const InputWindowInfo* info = windowHandle->getInfo();
-                    if (info) {
-                        ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(info->displayId);
-                        if (stateIndex >= 0) {
-                            mTouchStatesByDisplay.editValueAt(stateIndex).removeWindow(
-                                    windowHandle);
-                        }
-                    }
+                if (token != nullptr) {
+                    removeWindowByTokenLocked(token);
                 }
 
                 if (connection->status == Connection::STATUS_NORMAL) {
@@ -3640,8 +3640,7 @@
             mConfig.keyRepeatTimeout * 0.000001f);
 }
 
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
-        const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId) {
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, int32_t displayId) {
 #if DEBUG_REGISTRATION
     ALOGD("channel '%s' ~ registerInputChannel - displayId=%" PRId32,
             inputChannel->getName().c_str(), displayId);
@@ -3658,9 +3657,9 @@
 
         // If InputWindowHandle is null and displayId is not ADISPLAY_ID_NONE,
         // treat inputChannel as monitor channel for displayId.
-        bool monitor = inputWindowHandle == nullptr && displayId != ADISPLAY_ID_NONE;
+        bool monitor = inputChannel->getToken() == nullptr && displayId != ADISPLAY_ID_NONE;
 
-        sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
+        sp<Connection> connection = new Connection(inputChannel, monitor);
 
         int fd = inputChannel->getFd();
         mConnectionsByFd.add(fd, connection);
@@ -3809,7 +3808,7 @@
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doNotifyANRLockedInterruptible);
     commandEntry->inputApplicationHandle = applicationHandle;
-    commandEntry->inputWindowHandle = windowHandle;
+    commandEntry->inputChannel = windowHandle != nullptr ? windowHandle->getInputChannel() : nullptr;
     commandEntry->reason = reason;
 }
 
@@ -3829,7 +3828,7 @@
     if (connection->status != Connection::STATUS_ZOMBIE) {
         mLock.unlock();
 
-        mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
+        mPolicy->notifyInputChannelBroken(connection->inputChannel->getToken());
 
         mLock.lock();
     }
@@ -3840,14 +3839,14 @@
     mLock.unlock();
 
     nsecs_t newTimeout = mPolicy->notifyANR(
-            commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle,
+            commandEntry->inputApplicationHandle,
+            commandEntry->inputChannel ? commandEntry->inputChannel->getToken() : nullptr,
             commandEntry->reason);
 
     mLock.lock();
 
     resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
-            commandEntry->inputWindowHandle != nullptr
-                    ? commandEntry->inputWindowHandle->getInputChannel() : nullptr);
+            commandEntry->inputChannel);
 }
 
 void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
@@ -3860,7 +3859,9 @@
     mLock.unlock();
 
     android::base::Timer t;
-    nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
+    sp<IBinder> token = commandEntry->inputChannel != nullptr ?
+        commandEntry->inputChannel->getToken() : nullptr;
+    nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(token,
             &event, entry->policyFlags);
     if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
         ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
@@ -3961,7 +3962,7 @@
 
                 mLock.unlock();
 
-                mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
+                mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
                         &event, keyEntry->policyFlags, &event);
 
                 mLock.lock();
@@ -4006,7 +4007,7 @@
 
             mLock.unlock();
 
-            bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
+            bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
                     &event, keyEntry->policyFlags, &event);
 
             mLock.lock();
@@ -4722,9 +4723,8 @@
 
 // --- InputDispatcher::Connection ---
 
-InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
-        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) :
-        status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
+InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel, bool monitor) :
+        status(STATUS_NORMAL), inputChannel(inputChannel),
         monitor(monitor),
         inputPublisher(inputChannel), inputPublisherBlocked(false) {
 }
@@ -4733,8 +4733,8 @@
 }
 
 const std::string InputDispatcher::Connection::getWindowName() const {
-    if (inputWindowHandle != nullptr) {
-        return inputWindowHandle->getName();
+    if (inputChannel != nullptr) {
+        return inputChannel->getName();
     }
     if (monitor) {
         return "monitor";
@@ -4841,6 +4841,15 @@
     }
 }
 
+void InputDispatcher::TouchState::removeWindowByToken(const sp<IBinder>& token) {
+    for (size_t i = 0; i < windows.size(); i++) {
+        if (windows.itemAt(i).windowHandle->getInputChannel()->getToken() == token) {
+            windows.removeAt(i);
+            return;
+        }
+    }
+}
+
 void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
     for (size_t i = 0 ; i < windows.size(); ) {
         TouchedWindow& window = windows.editItemAt(i);
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 5efb2fa..5016082 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -208,11 +208,11 @@
     /* Notifies the system that an application is not responding.
      * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputWindowHandle>& inputWindowHandle,
+            const sp<IBinder>& token,
             const std::string& reason) = 0;
 
     /* Notifies the system that an input channel is unrecoverably broken. */
-    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
+    virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
 
     /* Gets the input dispatcher configuration. */
     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
@@ -243,12 +243,12 @@
     virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
 
     /* Allows the policy a chance to intercept a key before dispatching. */
-    virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
+    virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token,
             const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
 
     /* Allows the policy a chance to perform default processing for an unhandled key.
      * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
-    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
+    virtual bool dispatchUnhandledKey(const sp<IBinder>& token,
             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
 
     /* Notifies the policy about switch events.
@@ -352,8 +352,8 @@
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-            const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId) = 0;
+    virtual status_t registerInputChannel(
+            const sp<InputChannel>& inputChannel, int32_t displayId) = 0;
 
     /* Unregister input channels that will no longer receive input events.
      *
@@ -413,7 +413,7 @@
             const sp<InputChannel>& toChannel);
 
     virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-            const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId);
+            int32_t displayId);
     virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
 
 private:
@@ -617,11 +617,11 @@
         nsecs_t eventTime;
         KeyEntry* keyEntry;
         sp<InputApplicationHandle> inputApplicationHandle;
-        sp<InputWindowHandle> inputWindowHandle;
         std::string reason;
         int32_t userActivityEventType;
         uint32_t seq;
         bool handled;
+        sp<InputChannel> inputChannel;
     };
 
     // Generic queue implementation.
@@ -834,7 +834,6 @@
 
         Status status;
         sp<InputChannel> inputChannel; // never null
-        sp<InputWindowHandle> inputWindowHandle; // may be null
         bool monitor;
         InputPublisher inputPublisher;
         InputState inputState;
@@ -850,8 +849,7 @@
         // yet received a "finished" response from the application.
         Queue<DispatchEntry> waitQueue;
 
-        explicit Connection(const sp<InputChannel>& inputChannel,
-                const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
+        explicit Connection(const sp<InputChannel>& inputChannel, bool monitor);
 
         inline const std::string getInputChannelName() const { return inputChannel->getName(); }
 
@@ -1007,6 +1005,7 @@
         void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
                 int32_t targetFlags, BitSet32 pointerIds);
         void removeWindow(const sp<InputWindowHandle>& windowHandle);
+        void removeWindowByToken(const sp<IBinder>& token);
         void filterNonAsIsTouchWindows();
         sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
         bool isSlippery() const;
@@ -1062,6 +1061,9 @@
             const sp<InputApplicationHandle>& applicationHandle,
             const sp<InputWindowHandle>& windowHandle,
             nsecs_t* nextWakeupTime, const char* reason);
+
+    void removeWindowByTokenLocked(const sp<IBinder>& token);
+
     void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
             const sp<InputChannel>& inputChannel);
     nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index a1cd71c..ea42855 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -15,6 +15,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libbinder",
         "libcutils",
         "liblog",
         "libutils",
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 066c143..0780704 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -16,6 +16,8 @@
 
 #include "../InputDispatcher.h"
 
+#include <binder/Binder.h>
+
 #include <gtest/gtest.h>
 #include <linux/input.h>
 
@@ -53,12 +55,12 @@
     }
 
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>&,
-            const sp<InputWindowHandle>&,
+            const sp<IBinder>&,
             const std::string&) {
         return 0;
     }
 
-    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>&) {
+    virtual void notifyInputChannelBroken(const sp<IBinder>&) {
     }
 
     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
@@ -75,12 +77,12 @@
     virtual void interceptMotionBeforeQueueing(nsecs_t, uint32_t&) {
     }
 
-    virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>&,
+    virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&,
             const KeyEvent*, uint32_t) {
         return 0;
     }
 
-    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>&,
+    virtual bool dispatchUnhandledKey(const sp<IBinder>&,
             const KeyEvent*, uint32_t, KeyEvent*) {
         return false;
     }
@@ -336,6 +338,8 @@
             const std::string name, int32_t displayId) :
                 mDispatcher(dispatcher), mName(name), mDisplayId(displayId) {
             InputChannel::openInputChannelPair(name, mServerChannel, mClientChannel);
+            mServerChannel->setToken(new BBinder());
+
             mConsumer = new InputConsumer(mClientChannel);
         }
 
@@ -366,7 +370,7 @@
             InputWindowHandle(inputApplicationHandle),
             FakeInputReceiver(dispatcher, name, displayId),
             mFocused(false) {
-            mDispatcher->registerInputChannel(mServerChannel, this, displayId);
+            mDispatcher->registerInputChannel(mServerChannel, displayId);
     }
 
     virtual bool updateInfo() {
@@ -649,7 +653,7 @@
 public:
     FakeMonitorReceiver(const sp<InputDispatcher>& dispatcher, const std::string name,
             int32_t displayId) : FakeInputReceiver(dispatcher, name, displayId) {
-        mDispatcher->registerInputChannel(mServerChannel, nullptr, displayId);
+        mDispatcher->registerInputChannel(mServerChannel, displayId);
     }
 };