Loading include/input/InputTransport.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -246,6 +246,8 @@ public: /* Return a new object that has a duplicate of this channel's fd. */ /* Return a new object that has a duplicate of this channel's fd. */ std::unique_ptr<InputChannel> dup() const; std::unique_ptr<InputChannel> dup() const; void copyTo(InputChannel& outChannel) const; status_t readFromParcel(const android::Parcel* parcel) override; status_t readFromParcel(const android::Parcel* parcel) override; status_t writeToParcel(android::Parcel* parcel) const override; status_t writeToParcel(android::Parcel* parcel) const override; Loading Loading @@ -277,6 +279,8 @@ public: } } private: private: base::unique_fd dupFd() const; std::string mName; std::string mName; android::base::unique_fd mFd; android::base::unique_fd mFd; Loading libs/gui/tests/EndToEndNativeInputTest.cpp +4 −7 Original line number Original line Diff line number Diff line Loading @@ -68,12 +68,10 @@ class InputSurface { public: public: InputSurface(const sp<SurfaceControl> &sc, int width, int height) { InputSurface(const sp<SurfaceControl> &sc, int width, int height) { mSurfaceControl = sc; mSurfaceControl = sc; std::unique_ptr<InputChannel> clientChannel; InputChannel::openInputChannelPair("testchannels", mServerChannel, clientChannel); mClientChannel = std::move(clientChannel); mInputFlinger = getInputFlinger(); mInputFlinger = getInputFlinger(); mInputFlinger->registerInputChannel(*mServerChannel); mClientChannel = std::make_shared<InputChannel>(); mInputFlinger->createInputChannel("testchannels", mClientChannel.get()); populateInputInfo(width, height); populateInputInfo(width, height); Loading Loading @@ -155,7 +153,7 @@ public: EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); } } ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel->getConnectionToken()); } ~InputSurface() { mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); } void doTransaction(std::function<void(SurfaceComposerClient::Transaction&, void doTransaction(std::function<void(SurfaceComposerClient::Transaction&, const sp<SurfaceControl>&)> transactionBody) { const sp<SurfaceControl>&)> transactionBody) { Loading Loading @@ -192,7 +190,7 @@ private: } } void populateInputInfo(int width, int height) { void populateInputInfo(int width, int height) { mInputInfo.token = mServerChannel->getConnectionToken(); mInputInfo.token = mClientChannel->getConnectionToken(); mInputInfo.name = "Test info"; mInputInfo.name = "Test info"; mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION; mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION; Loading @@ -219,7 +217,6 @@ private: } } public: public: sp<SurfaceControl> mSurfaceControl; sp<SurfaceControl> mSurfaceControl; std::unique_ptr<InputChannel> mServerChannel; std::shared_ptr<InputChannel> mClientChannel; std::shared_ptr<InputChannel> mClientChannel; sp<IInputFlinger> mInputFlinger; sp<IInputFlinger> mInputFlinger; Loading libs/input/InputTransport.cpp +24 −13 Original line number Original line Diff line number Diff line Loading @@ -377,22 +377,16 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { } } std::unique_ptr<InputChannel> InputChannel::dup() const { std::unique_ptr<InputChannel> InputChannel::dup() const { android::base::unique_fd newFd(::dup(getFd())); base::unique_fd newFd(dupFd()); if (!newFd.ok()) { ALOGE("Could not duplicate fd %i for channel %s: %s", getFd().get(), getName().c_str(), strerror(errno)); const bool hitFdLimit = errno == EMFILE || errno == ENFILE; // If this process is out of file descriptors, then throwing that might end up exploding // on the other side of a binder call, which isn't really helpful. // Better to just crash here and hope that the FD leak is slow. // Other failures could be client errors, so we still propagate those back to the caller. LOG_ALWAYS_FATAL_IF(hitFdLimit, "Too many open files, could not duplicate input channel %s", getName().c_str()); return nullptr; } return InputChannel::create(getName(), std::move(newFd), getConnectionToken()); return InputChannel::create(getName(), std::move(newFd), getConnectionToken()); } } void InputChannel::copyTo(InputChannel& outChannel) const { outChannel.mName = getName(); outChannel.mFd = dupFd(); outChannel.mToken = getConnectionToken(); } status_t InputChannel::writeToParcel(android::Parcel* parcel) const { status_t InputChannel::writeToParcel(android::Parcel* parcel) const { if (parcel == nullptr) { if (parcel == nullptr) { ALOGE("%s: Null parcel", __func__); ALOGE("%s: Null parcel", __func__); Loading @@ -415,6 +409,23 @@ sp<IBinder> InputChannel::getConnectionToken() const { return mToken; return mToken; } } base::unique_fd InputChannel::dupFd() const { android::base::unique_fd newFd(::dup(getFd())); if (!newFd.ok()) { ALOGE("Could not duplicate fd %i for channel %s: %s", getFd().get(), getName().c_str(), strerror(errno)); const bool hitFdLimit = errno == EMFILE || errno == ENFILE; // If this process is out of file descriptors, then throwing that might end up exploding // on the other side of a binder call, which isn't really helpful. // Better to just crash here and hope that the FD leak is slow. // Other failures could be client errors, so we still propagate those back to the caller. LOG_ALWAYS_FATAL_IF(hitFdLimit, "Too many open files, could not duplicate input channel %s", getName().c_str()); return {}; } return newFd; } // --- InputPublisher --- // --- InputPublisher --- InputPublisher::InputPublisher(const std::shared_ptr<InputChannel>& channel) : mChannel(channel) {} InputPublisher::InputPublisher(const std::shared_ptr<InputChannel>& channel) : mChannel(channel) {} Loading libs/input/android/os/IInputFlinger.aidl +2 −2 Original line number Original line Diff line number Diff line Loading @@ -30,8 +30,8 @@ interface IInputFlinger // shouldn't be a concern. // shouldn't be a concern. oneway void setInputWindows(in InputWindowInfo[] inputHandles, oneway void setInputWindows(in InputWindowInfo[] inputHandles, in @nullable ISetInputWindowsListener setInputWindowsListener); in @nullable ISetInputWindowsListener setInputWindowsListener); void registerInputChannel(in InputChannel channel); InputChannel createInputChannel(in @utf8InCpp String name); void unregisterInputChannel(in IBinder connectionToken); void removeInputChannel(in IBinder connectionToken); /** /** * Sets focus to the window identified by the token. This must be called * Sets focus to the window identified by the token. This must be called * after updating any input window handles. * after updating any input window handles. Loading services/inputflinger/InputManager.cpp +28 −4 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,25 @@ namespace android { namespace android { static int32_t exceptionCodeFromStatusT(status_t status) { switch (status) { case OK: return binder::Status::EX_NONE; case INVALID_OPERATION: return binder::Status::EX_UNSUPPORTED_OPERATION; case BAD_VALUE: case BAD_TYPE: case NAME_NOT_FOUND: return binder::Status::EX_ILLEGAL_ARGUMENT; case NO_INIT: return binder::Status::EX_ILLEGAL_STATE; case PERMISSION_DENIED: return binder::Status::EX_SECURITY; default: return binder::Status::EX_TRANSACTION_FAILED; } } InputManager::InputManager( InputManager::InputManager( const sp<InputReaderPolicyInterface>& readerPolicy, const sp<InputReaderPolicyInterface>& readerPolicy, const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) { const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) { Loading Loading @@ -119,7 +138,7 @@ binder::Status InputManager::setInputWindows( } } // Used by tests only. // Used by tests only. binder::Status InputManager::registerInputChannel(const InputChannel& channel) { binder::Status InputManager::createInputChannel(const std::string& name, InputChannel* outChannel) { IPCThreadState* ipc = IPCThreadState::self(); IPCThreadState* ipc = IPCThreadState::self(); const int uid = ipc->getCallingUid(); const int uid = ipc->getCallingUid(); if (uid != AID_SHELL && uid != AID_ROOT) { if (uid != AID_SHELL && uid != AID_ROOT) { Loading @@ -128,12 +147,17 @@ binder::Status InputManager::registerInputChannel(const InputChannel& channel) { return binder::Status::ok(); return binder::Status::ok(); } } mDispatcher->registerInputChannel(channel.dup()); base::Result<std::unique_ptr<InputChannel>> channel = mDispatcher->createInputChannel(name); if (!channel) { return binder::Status::fromExceptionCode(exceptionCodeFromStatusT(channel.error().code()), channel.error().message().c_str()); } (*channel)->copyTo(*outChannel); return binder::Status::ok(); return binder::Status::ok(); } } binder::Status InputManager::unregisterInputChannel(const sp<IBinder>& connectionToken) { binder::Status InputManager::removeInputChannel(const sp<IBinder>& connectionToken) { mDispatcher->unregisterInputChannel(connectionToken); mDispatcher->removeInputChannel(connectionToken); return binder::Status::ok(); return binder::Status::ok(); } } Loading Loading
include/input/InputTransport.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -246,6 +246,8 @@ public: /* Return a new object that has a duplicate of this channel's fd. */ /* Return a new object that has a duplicate of this channel's fd. */ std::unique_ptr<InputChannel> dup() const; std::unique_ptr<InputChannel> dup() const; void copyTo(InputChannel& outChannel) const; status_t readFromParcel(const android::Parcel* parcel) override; status_t readFromParcel(const android::Parcel* parcel) override; status_t writeToParcel(android::Parcel* parcel) const override; status_t writeToParcel(android::Parcel* parcel) const override; Loading Loading @@ -277,6 +279,8 @@ public: } } private: private: base::unique_fd dupFd() const; std::string mName; std::string mName; android::base::unique_fd mFd; android::base::unique_fd mFd; Loading
libs/gui/tests/EndToEndNativeInputTest.cpp +4 −7 Original line number Original line Diff line number Diff line Loading @@ -68,12 +68,10 @@ class InputSurface { public: public: InputSurface(const sp<SurfaceControl> &sc, int width, int height) { InputSurface(const sp<SurfaceControl> &sc, int width, int height) { mSurfaceControl = sc; mSurfaceControl = sc; std::unique_ptr<InputChannel> clientChannel; InputChannel::openInputChannelPair("testchannels", mServerChannel, clientChannel); mClientChannel = std::move(clientChannel); mInputFlinger = getInputFlinger(); mInputFlinger = getInputFlinger(); mInputFlinger->registerInputChannel(*mServerChannel); mClientChannel = std::make_shared<InputChannel>(); mInputFlinger->createInputChannel("testchannels", mClientChannel.get()); populateInputInfo(width, height); populateInputInfo(width, height); Loading Loading @@ -155,7 +153,7 @@ public: EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); } } ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel->getConnectionToken()); } ~InputSurface() { mInputFlinger->removeInputChannel(mClientChannel->getConnectionToken()); } void doTransaction(std::function<void(SurfaceComposerClient::Transaction&, void doTransaction(std::function<void(SurfaceComposerClient::Transaction&, const sp<SurfaceControl>&)> transactionBody) { const sp<SurfaceControl>&)> transactionBody) { Loading Loading @@ -192,7 +190,7 @@ private: } } void populateInputInfo(int width, int height) { void populateInputInfo(int width, int height) { mInputInfo.token = mServerChannel->getConnectionToken(); mInputInfo.token = mClientChannel->getConnectionToken(); mInputInfo.name = "Test info"; mInputInfo.name = "Test info"; mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION; mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION; Loading @@ -219,7 +217,6 @@ private: } } public: public: sp<SurfaceControl> mSurfaceControl; sp<SurfaceControl> mSurfaceControl; std::unique_ptr<InputChannel> mServerChannel; std::shared_ptr<InputChannel> mClientChannel; std::shared_ptr<InputChannel> mClientChannel; sp<IInputFlinger> mInputFlinger; sp<IInputFlinger> mInputFlinger; Loading
libs/input/InputTransport.cpp +24 −13 Original line number Original line Diff line number Diff line Loading @@ -377,22 +377,16 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { } } std::unique_ptr<InputChannel> InputChannel::dup() const { std::unique_ptr<InputChannel> InputChannel::dup() const { android::base::unique_fd newFd(::dup(getFd())); base::unique_fd newFd(dupFd()); if (!newFd.ok()) { ALOGE("Could not duplicate fd %i for channel %s: %s", getFd().get(), getName().c_str(), strerror(errno)); const bool hitFdLimit = errno == EMFILE || errno == ENFILE; // If this process is out of file descriptors, then throwing that might end up exploding // on the other side of a binder call, which isn't really helpful. // Better to just crash here and hope that the FD leak is slow. // Other failures could be client errors, so we still propagate those back to the caller. LOG_ALWAYS_FATAL_IF(hitFdLimit, "Too many open files, could not duplicate input channel %s", getName().c_str()); return nullptr; } return InputChannel::create(getName(), std::move(newFd), getConnectionToken()); return InputChannel::create(getName(), std::move(newFd), getConnectionToken()); } } void InputChannel::copyTo(InputChannel& outChannel) const { outChannel.mName = getName(); outChannel.mFd = dupFd(); outChannel.mToken = getConnectionToken(); } status_t InputChannel::writeToParcel(android::Parcel* parcel) const { status_t InputChannel::writeToParcel(android::Parcel* parcel) const { if (parcel == nullptr) { if (parcel == nullptr) { ALOGE("%s: Null parcel", __func__); ALOGE("%s: Null parcel", __func__); Loading @@ -415,6 +409,23 @@ sp<IBinder> InputChannel::getConnectionToken() const { return mToken; return mToken; } } base::unique_fd InputChannel::dupFd() const { android::base::unique_fd newFd(::dup(getFd())); if (!newFd.ok()) { ALOGE("Could not duplicate fd %i for channel %s: %s", getFd().get(), getName().c_str(), strerror(errno)); const bool hitFdLimit = errno == EMFILE || errno == ENFILE; // If this process is out of file descriptors, then throwing that might end up exploding // on the other side of a binder call, which isn't really helpful. // Better to just crash here and hope that the FD leak is slow. // Other failures could be client errors, so we still propagate those back to the caller. LOG_ALWAYS_FATAL_IF(hitFdLimit, "Too many open files, could not duplicate input channel %s", getName().c_str()); return {}; } return newFd; } // --- InputPublisher --- // --- InputPublisher --- InputPublisher::InputPublisher(const std::shared_ptr<InputChannel>& channel) : mChannel(channel) {} InputPublisher::InputPublisher(const std::shared_ptr<InputChannel>& channel) : mChannel(channel) {} Loading
libs/input/android/os/IInputFlinger.aidl +2 −2 Original line number Original line Diff line number Diff line Loading @@ -30,8 +30,8 @@ interface IInputFlinger // shouldn't be a concern. // shouldn't be a concern. oneway void setInputWindows(in InputWindowInfo[] inputHandles, oneway void setInputWindows(in InputWindowInfo[] inputHandles, in @nullable ISetInputWindowsListener setInputWindowsListener); in @nullable ISetInputWindowsListener setInputWindowsListener); void registerInputChannel(in InputChannel channel); InputChannel createInputChannel(in @utf8InCpp String name); void unregisterInputChannel(in IBinder connectionToken); void removeInputChannel(in IBinder connectionToken); /** /** * Sets focus to the window identified by the token. This must be called * Sets focus to the window identified by the token. This must be called * after updating any input window handles. * after updating any input window handles. Loading
services/inputflinger/InputManager.cpp +28 −4 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,25 @@ namespace android { namespace android { static int32_t exceptionCodeFromStatusT(status_t status) { switch (status) { case OK: return binder::Status::EX_NONE; case INVALID_OPERATION: return binder::Status::EX_UNSUPPORTED_OPERATION; case BAD_VALUE: case BAD_TYPE: case NAME_NOT_FOUND: return binder::Status::EX_ILLEGAL_ARGUMENT; case NO_INIT: return binder::Status::EX_ILLEGAL_STATE; case PERMISSION_DENIED: return binder::Status::EX_SECURITY; default: return binder::Status::EX_TRANSACTION_FAILED; } } InputManager::InputManager( InputManager::InputManager( const sp<InputReaderPolicyInterface>& readerPolicy, const sp<InputReaderPolicyInterface>& readerPolicy, const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) { const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) { Loading Loading @@ -119,7 +138,7 @@ binder::Status InputManager::setInputWindows( } } // Used by tests only. // Used by tests only. binder::Status InputManager::registerInputChannel(const InputChannel& channel) { binder::Status InputManager::createInputChannel(const std::string& name, InputChannel* outChannel) { IPCThreadState* ipc = IPCThreadState::self(); IPCThreadState* ipc = IPCThreadState::self(); const int uid = ipc->getCallingUid(); const int uid = ipc->getCallingUid(); if (uid != AID_SHELL && uid != AID_ROOT) { if (uid != AID_SHELL && uid != AID_ROOT) { Loading @@ -128,12 +147,17 @@ binder::Status InputManager::registerInputChannel(const InputChannel& channel) { return binder::Status::ok(); return binder::Status::ok(); } } mDispatcher->registerInputChannel(channel.dup()); base::Result<std::unique_ptr<InputChannel>> channel = mDispatcher->createInputChannel(name); if (!channel) { return binder::Status::fromExceptionCode(exceptionCodeFromStatusT(channel.error().code()), channel.error().message().c_str()); } (*channel)->copyTo(*outChannel); return binder::Status::ok(); return binder::Status::ok(); } } binder::Status InputManager::unregisterInputChannel(const sp<IBinder>& connectionToken) { binder::Status InputManager::removeInputChannel(const sp<IBinder>& connectionToken) { mDispatcher->unregisterInputChannel(connectionToken); mDispatcher->removeInputChannel(connectionToken); return binder::Status::ok(); return binder::Status::ok(); } } Loading