diff options
author | 2018-12-26 12:23:37 -0800 | |
---|---|---|
committer | 2019-01-08 16:04:04 -0800 | |
commit | fbe5d9c4233dcd802a122f70ca5a3641fcd556ca (patch) | |
tree | 2df71b9465c29c751216d3e762efd0a4dd09d0fb | |
parent | aab8d1f8b088dd2376da2aa630669905166937d4 (diff) |
Fix drag and drop (2/3)
Handle InputWindowCommands in SurfaceFlinger. Send transferTouchFocus from
SurfaceFlinger to InputFlinger.
Test: InputSurfacesTest.transfer_touch_focus
Bug: 120463595
Change-Id: I6592cc9ee4a77700ea191fd1ca337b91895b61fe
-rw-r--r-- | include/input/IInputFlinger.h | 5 | ||||
-rw-r--r-- | libs/gui/tests/EndToEndNativeInputTest.cpp | 50 | ||||
-rw-r--r-- | libs/input/IInputFlinger.cpp | 17 | ||||
-rw-r--r-- | services/inputflinger/InputDispatcher.cpp | 37 | ||||
-rw-r--r-- | services/inputflinger/InputDispatcher.h | 8 | ||||
-rw-r--r-- | services/inputflinger/InputManager.cpp | 4 | ||||
-rw-r--r-- | services/inputflinger/InputManager.h | 1 | ||||
-rw-r--r-- | services/inputflinger/host/InputFlinger.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 18 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 1 |
10 files changed, 122 insertions, 20 deletions
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h index 610834d23e..ff443c6928 100644 --- a/include/input/IInputFlinger.h +++ b/include/input/IInputFlinger.h @@ -36,7 +36,7 @@ public: DECLARE_META_INTERFACE(InputFlinger) virtual void setInputWindows(const Vector<InputWindowInfo>& inputHandles) = 0; - + virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0; virtual void registerInputChannel(const sp<InputChannel>& channel) = 0; virtual void unregisterInputChannel(const sp<InputChannel>& channel) = 0; }; @@ -50,7 +50,8 @@ public: enum { SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, REGISTER_INPUT_CHANNEL_TRANSACTION, - UNREGISTER_INPUT_CHANNEL_TRANSACTION + UNREGISTER_INPUT_CHANNEL_TRANSACTION, + TRANSFER_TOUCH_FOCUS }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 60542bd47c..7fc69ff93b 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -133,6 +133,27 @@ public: EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); } + void expectMotionEvent(int motionEventType, int x, int y) { + InputEvent *ev = consumeEvent(); + ASSERT_NE(ev, nullptr); + ASSERT_EQ(ev->getType(), AINPUT_EVENT_TYPE_MOTION); + MotionEvent *mev = static_cast<MotionEvent *>(ev); + EXPECT_EQ(motionEventType, mev->getAction()); + EXPECT_EQ(x, mev->getX(0)); + EXPECT_EQ(y, mev->getY(0)); + } + + void expectNoMotionEvent(int motionEventType) { + InputEvent *ev = consumeEvent(); + if (ev == nullptr || ev->getType() != AINPUT_EVENT_TYPE_MOTION) { + // Didn't find an event or a motion event so assume action didn't occur. + return; + } + + MotionEvent *mev = static_cast<MotionEvent *>(ev); + EXPECT_NE(motionEventType, mev->getAction()); + } + ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel); } @@ -255,6 +276,15 @@ void injectTap(int x, int y) { } } +void injectMotionEvent(std::string event, int x, int y) { + char *buf1, *buf2; + asprintf(&buf1, "%d", x); + asprintf(&buf2, "%d", y); + if (fork() == 0) { + execlp("input", "input", "motionevent", event.c_str(), buf1, buf2, NULL); + } +} + TEST_F(InputSurfacesTest, can_receive_input) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); @@ -439,5 +469,25 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { injectTap(11, 11); bgSurface->expectTap(1, 1); } + +TEST_F(InputSurfacesTest, transfer_touch_focus) { + std::unique_ptr<InputSurface> fromSurface = makeSurface(100, 100); + + fromSurface->showAt(10, 10); + injectMotionEvent("DOWN", 11, 11); + fromSurface->expectMotionEvent(AMOTION_EVENT_ACTION_DOWN, 1, 1); + + std::unique_ptr<InputSurface> toSurface = makeSurface(100, 100); + toSurface->showAt(10, 10); + + sp<IBinder> fromToken = fromSurface->mServerChannel->getToken(); + sp<IBinder> toToken = toSurface->mServerChannel->getToken(); + SurfaceComposerClient::Transaction t; + t.transferTouchFocus(fromToken, toToken).apply(true); + + injectMotionEvent("UP", 11, 11); + toSurface->expectMotionEvent(AMOTION_EVENT_ACTION_UP, 1, 1); + fromSurface->expectNoMotionEvent(AMOTION_EVENT_ACTION_UP); +} } } diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp index 139570a5fd..acf40bcbde 100644 --- a/libs/input/IInputFlinger.cpp +++ b/libs/input/IInputFlinger.cpp @@ -42,6 +42,16 @@ public: IBinder::FLAG_ONEWAY); } + virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) { + Parcel data, reply; + data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); + + data.writeStrongBinder(fromToken); + data.writeStrongBinder(toToken); + remote()->transact(BnInputFlinger::TRANSFER_TOUCH_FOCUS, data, &reply, + IBinder::FLAG_ONEWAY); + } + virtual void registerInputChannel(const sp<InputChannel>& channel) { Parcel data, reply; data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); @@ -90,6 +100,13 @@ status_t BnInputFlinger::onTransact( unregisterInputChannel(channel); break; } + case TRANSFER_TOUCH_FOCUS: { + CHECK_INTERFACE(IInputFlinger, data, reply); + sp<IBinder> fromToken = data.readStrongBinder(); + sp<IBinder> toToken = data.readStrongBinder(); + transferTouchFocus(fromToken, toToken); + break; + } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp index 6173452166..7997928624 100644 --- a/services/inputflinger/InputDispatcher.cpp +++ b/services/inputflinger/InputDispatcher.cpp @@ -2386,7 +2386,8 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( } InputTarget target; - sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel); + sp<InputWindowHandle> windowHandle = getWindowHandleLocked( + connection->inputChannel->getToken()); if (windowHandle != nullptr) { const InputWindowInfo* windowInfo = windowHandle->getInfo(); target.xOffset = -windowInfo->frameLeft; @@ -3024,13 +3025,13 @@ Vector<sp<InputWindowHandle>> InputDispatcher::getWindowHandlesLocked(int32_t di } sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked( - const sp<InputChannel>& inputChannel) const { + const sp<IBinder>& windowHandleToken) const { for (auto& it : mWindowHandlesByDisplay) { const Vector<sp<InputWindowHandle>> windowHandles = it.second; size_t numWindows = windowHandles.size(); for (size_t i = 0; i < numWindows; i++) { const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i); - if (windowHandle->getToken() == inputChannel->getToken()) { + if (windowHandle->getToken() == windowHandleToken) { return windowHandle; } } @@ -3375,27 +3376,30 @@ void InputDispatcher::setInputFilterEnabled(bool enabled) { bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel, const sp<InputChannel>& toChannel) { + return transferTouchFocus(fromChannel->getToken(), toChannel->getToken()); +} + +bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) { + if (fromToken == toToken) { #if DEBUG_FOCUS - ALOGD("transferTouchFocus: fromChannel=%s, toChannel=%s", - fromChannel->getName().c_str(), toChannel->getName().c_str()); + ALOGD("Trivial transfer to same window."); #endif + return true; + } + { // acquire lock AutoMutex _l(mLock); - sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel); - sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel); - if (fromWindowHandle == nullptr || toWindowHandle == nullptr) { + sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromToken); + sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toToken); #if DEBUG_FOCUS - ALOGD("Cannot transfer focus because from or to window not found."); + ALOGD("transferTouchFocus: fromWindowHandle=%s, toWindowHandle=%s", + fromWindowHandle->getName().c_str(), toWindowHandle->getName().c_str()); #endif + if (fromWindowHandle == nullptr || toWindowHandle == nullptr) { + ALOGW("Cannot transfer focus because from or to window not found."); return false; } - if (fromWindowHandle == toWindowHandle) { -#if DEBUG_FOCUS - ALOGD("Trivial transfer to same window."); -#endif - return true; - } if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) { #if DEBUG_FOCUS ALOGD("Cannot transfer focus because windows are on different displays."); @@ -3433,6 +3437,9 @@ Found: return false; } + + sp<InputChannel> fromChannel = getInputChannelLocked(fromToken); + sp<InputChannel> toChannel = getInputChannelLocked(toToken); ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel); ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel); if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) { diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h index 7e6de6a2d9..970632e5e2 100644 --- a/services/inputflinger/InputDispatcher.h +++ b/services/inputflinger/InputDispatcher.h @@ -343,11 +343,12 @@ public: */ virtual void setInputFilterEnabled(bool enabled) = 0; - /* Transfers touch focus from the window associated with one channel to the - * window associated with the other channel. + /* Transfers touch focus from one window to another window. * * Returns true on success. False if the window did not actually have touch focus. */ + virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0; + virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel, const sp<InputChannel>& toChannel) = 0; @@ -414,6 +415,7 @@ public: virtual void setInputDispatchMode(bool enabled, bool frozen); virtual void setInputFilterEnabled(bool enabled); + virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken); virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel, const sp<InputChannel>& toChannel); @@ -995,7 +997,7 @@ private: std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay; // Get window handles by display, return an empty vector if not found. Vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const; - sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const; + sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken) const; sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const; bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const; diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index 15d80703aa..1d7ea00e0c 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -111,6 +111,10 @@ void InputManager::setInputWindows(const Vector<InputWindowInfo>& infos) { } } +void InputManager::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) { + mDispatcher->transferTouchFocus(fromToken, toToken); +} + // Used by tests only. void InputManager::registerInputChannel(const sp<InputChannel>& channel) { IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index 8f7551e5b2..ab309b1888 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -91,6 +91,7 @@ public: virtual sp<InputDispatcherInterface> getDispatcher(); virtual void setInputWindows(const Vector<InputWindowInfo>& handles); + virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken); virtual void registerInputChannel(const sp<InputChannel>& channel); virtual void unregisterInputChannel(const sp<InputChannel>& channel); diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h index 82ff089e89..9d0be95976 100644 --- a/services/inputflinger/host/InputFlinger.h +++ b/services/inputflinger/host/InputFlinger.h @@ -40,6 +40,7 @@ public: virtual status_t dump(int fd, const Vector<String16>& args); void setInputWindows(const Vector<InputWindowInfo>&) {} + void transferTouchFocus(const sp<IBinder>&, const sp<IBinder>&) {} void registerInputChannel(const sp<InputChannel>&) {} void unregisterInputChannel(const sp<InputChannel>&) {} diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 13997bea21..467b7da27a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2738,6 +2738,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (inputChanged || mVisibleRegionsDirty) { updateInputWindows(); } + executeInputWindowCommands(); updateCursorAsync(); } @@ -2762,6 +2763,23 @@ void SurfaceFlinger::updateInputWindows() { mInputFlinger->setInputWindows(inputHandles); } +void SurfaceFlinger::executeInputWindowCommands() { + if (!mInputFlinger) { + return; + } + + for (const auto& transferTouchFocusCommand : mInputWindowCommands.transferTouchFocusCommands) { + if (transferTouchFocusCommand.fromToken != nullptr && + transferTouchFocusCommand.toToken != nullptr && + transferTouchFocusCommand.fromToken != transferTouchFocusCommand.toToken) { + mInputFlinger->transferTouchFocus(transferTouchFocusCommand.fromToken, + transferTouchFocusCommand.toToken); + } + } + + mInputWindowCommands.clear(); +} + void SurfaceFlinger::updateCursorAsync() { for (const auto& [token, display] : mDisplays) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bfc87a02eb..38c2fda28e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -543,6 +543,7 @@ private: void handleTransactionLocked(uint32_t transactionFlags); void updateInputWindows(); + void executeInputWindowCommands(); void updateCursorAsync(); /* handlePageFlip - latch a new buffer if available and compute the dirty |