Loading include/input/IInputFlinger.h +3 −2 Original line number Diff line number Diff line Loading @@ -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; }; Loading @@ -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, Loading libs/gui/tests/EndToEndNativeInputTest.cpp +50 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -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); } } } libs/input/IInputFlinger.cpp +17 −0 Original line number Diff line number Diff line Loading @@ -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()); Loading Loading @@ -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); } Loading services/inputflinger/InputDispatcher.cpp +22 −15 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } } Loading Loading @@ -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."); Loading Loading @@ -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) { Loading services/inputflinger/InputDispatcher.h +5 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading
include/input/IInputFlinger.h +3 −2 Original line number Diff line number Diff line Loading @@ -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; }; Loading @@ -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, Loading
libs/gui/tests/EndToEndNativeInputTest.cpp +50 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -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); } } }
libs/input/IInputFlinger.cpp +17 −0 Original line number Diff line number Diff line Loading @@ -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()); Loading Loading @@ -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); } Loading
services/inputflinger/InputDispatcher.cpp +22 −15 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } } Loading Loading @@ -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."); Loading Loading @@ -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) { Loading
services/inputflinger/InputDispatcher.h +5 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading