Loading include/input/InputTransport.h +12 −36 Original line number Diff line number Diff line Loading @@ -35,18 +35,16 @@ #include <android-base/result.h> #include <android-base/unique_fd.h> #include <android/os/InputChannelCore.h> #include <binder/IBinder.h> #include <binder/Parcelable.h> #include <input/Input.h> #include <input/InputVerifier.h> #include <sys/stat.h> #include <ui/Transform.h> #include <utils/BitSet.h> #include <utils/Errors.h> #include <utils/RefBase.h> #include <utils/Timers.h> namespace android { class Parcel; Loading Loading @@ -231,18 +229,15 @@ struct InputMessage { * input messages across processes. Each channel has a descriptive name for debugging purposes. * * Each endpoint has its own InputChannel object that specifies its file descriptor. * For parceling, this relies on android::os::InputChannelCore, defined in aidl. * * The input channel is closed when all references to it are released. */ class InputChannel : public Parcelable { class InputChannel : private android::os::InputChannelCore { public: static std::unique_ptr<InputChannel> create(const std::string& name, android::base::unique_fd fd, sp<IBinder> token); InputChannel() = default; InputChannel(const InputChannel& other) : mName(other.mName), mFd(other.dupFd()), mToken(other.mToken){}; InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token); ~InputChannel() override; static std::unique_ptr<InputChannel> create(android::os::InputChannelCore&& parceledChannel); ~InputChannel(); /** * Create a pair of input channels. * The two returned input channels are equivalent, and are labeled as "server" and "client" Loading @@ -254,9 +249,8 @@ public: std::unique_ptr<InputChannel>& outServerChannel, std::unique_ptr<InputChannel>& outClientChannel); inline std::string getName() const { return mName; } inline const android::base::unique_fd& getFd() const { return mFd; } inline sp<IBinder> getToken() const { return mToken; } inline std::string getName() const { return name; } inline int getFd() const { return fd.get(); } /* Send a message to the other endpoint. * Loading Loading @@ -304,10 +298,7 @@ public: /* Return a new object that has a duplicate of this channel's fd. */ std::unique_ptr<InputChannel> dup() const; void copyTo(InputChannel& outChannel) const; status_t readFromParcel(const android::Parcel* parcel) override; status_t writeToParcel(android::Parcel* parcel) const override; void copyTo(android::os::InputChannelCore& outChannel) const; /** * The connection token is used to identify the input connection, i.e. Loading @@ -323,26 +314,11 @@ public: */ sp<IBinder> getConnectionToken() const; bool operator==(const InputChannel& inputChannel) const { struct stat lhs, rhs; if (fstat(mFd.get(), &lhs) != 0) { return false; } if (fstat(inputChannel.getFd().get(), &rhs) != 0) { return false; } // If file descriptors are pointing to same inode they are duplicated fds. return inputChannel.getName() == getName() && inputChannel.getConnectionToken() == mToken && lhs.st_ino == rhs.st_ino; } private: base::unique_fd dupFd() const; std::string mName; base::unique_fd mFd; static std::unique_ptr<InputChannel> create(const std::string& name, android::base::unique_fd fd, sp<IBinder> token); sp<IBinder> mToken; InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token); }; /* Loading libs/gui/tests/EndToEndNativeInputTest.cpp +8 −4 Original line number Diff line number Diff line Loading @@ -63,8 +63,7 @@ namespace android::test { using Transaction = SurfaceComposerClient::Transaction; sp<IInputFlinger> getInputFlinger() { sp<IBinder> input(defaultServiceManager()->getService( String16("inputflinger"))); sp<IBinder> input(defaultServiceManager()->waitForService(String16("inputflinger"))); if (input == nullptr) { ALOGE("Failed to link to input service"); } else { ALOGE("Linked to input"); } Loading Loading @@ -104,8 +103,13 @@ public: if (noInputChannel) { mInputInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, true); } else { mClientChannel = std::make_shared<InputChannel>(); mInputFlinger->createInputChannel("testchannels", mClientChannel.get()); android::os::InputChannelCore tempChannel; android::binder::Status result = mInputFlinger->createInputChannel("testchannels", &tempChannel); if (!result.isOk()) { ADD_FAILURE() << "binder call to createInputChannel failed"; } mClientChannel = InputChannel::create(std::move(tempChannel)); mInputInfo.token = mClientChannel->getConnectionToken(); mInputConsumer = new InputConsumer(mClientChannel); } Loading libs/input/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -175,6 +175,7 @@ cc_library { ], srcs: [ "android/os/IInputFlinger.aidl", "android/os/InputChannelCore.aidl", "AccelerationCurve.cpp", "Input.cpp", "InputDevice.cpp", Loading libs/input/InputTransport.cpp +46 −58 Original line number Diff line number Diff line Loading @@ -95,6 +95,21 @@ bool debugResampling() { return __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Resampling", ANDROID_LOG_INFO); } android::base::unique_fd dupChannelFd(int fd) { android::base::unique_fd newFd(::dup(fd)); if (!newFd.ok()) { ALOGE("Could not duplicate fd %i : %s", fd, 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"); return {}; } return newFd; } } // namespace using android::base::Result; Loading Loading @@ -395,15 +410,23 @@ std::unique_ptr<InputChannel> InputChannel::create(const std::string& name, return std::unique_ptr<InputChannel>(new InputChannel(name, std::move(fd), token)); } InputChannel::InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token) : mName(std::move(name)), mFd(std::move(fd)), mToken(std::move(token)) { std::unique_ptr<InputChannel> InputChannel::create( android::os::InputChannelCore&& parceledChannel) { return InputChannel::create(parceledChannel.name, parceledChannel.fd.release(), parceledChannel.token); } InputChannel::InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token) { this->name = std::move(name); this->fd.reset(std::move(fd)); this->token = std::move(token); ALOGD_IF(DEBUG_CHANNEL_LIFECYCLE, "Input channel constructed: name='%s', fd=%d", getName().c_str(), getFd().get()); getName().c_str(), getFd()); } InputChannel::~InputChannel() { ALOGD_IF(DEBUG_CHANNEL_LIFECYCLE, "Input channel destroyed: name='%s', fd=%d", getName().c_str(), getFd().get()); getName().c_str(), getFd()); } status_t InputChannel::openInputChannelPair(const std::string& name, Loading Loading @@ -441,19 +464,19 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { ATRACE_NAME_IF(ATRACE_ENABLED(), StringPrintf("sendMessage(inputChannel=%s, seq=0x%" PRIx32 ", type=0x%" PRIx32 ")", mName.c_str(), msg->header.seq, msg->header.type)); name.c_str(), msg->header.seq, msg->header.type)); const size_t msgLength = msg->size(); InputMessage cleanMsg; msg->getSanitizedCopy(&cleanMsg); ssize_t nWrite; do { nWrite = ::send(getFd().get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); } while (nWrite == -1 && errno == EINTR); if (nWrite < 0) { int error = errno; ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ error sending message of type %s, %s", mName.c_str(), ftl::enum_string(msg->header.type).c_str(), strerror(error)); name.c_str(), ftl::enum_string(msg->header.type).c_str(), strerror(error)); if (error == EAGAIN || error == EWOULDBLOCK) { return WOULD_BLOCK; } Loading @@ -465,12 +488,12 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { if (size_t(nWrite) != msgLength) { ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ error sending message type %s, send was incomplete", mName.c_str(), "channel '%s' ~ error sending message type %s, send was incomplete", name.c_str(), ftl::enum_string(msg->header.type).c_str()); return DEAD_OBJECT; } ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ sent message of type %s", mName.c_str(), ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ sent message of type %s", name.c_str(), ftl::enum_string(msg->header.type).c_str()); return OK; Loading @@ -479,13 +502,13 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { status_t InputChannel::receiveMessage(InputMessage* msg) { ssize_t nRead; do { nRead = ::recv(getFd().get(), msg, sizeof(InputMessage), MSG_DONTWAIT); nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT); } while (nRead == -1 && errno == EINTR); if (nRead < 0) { int error = errno; ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ receive message failed, errno=%d", mName.c_str(), errno); name.c_str(), errno); if (error == EAGAIN || error == EWOULDBLOCK) { return WOULD_BLOCK; } Loading @@ -497,29 +520,29 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { if (nRead == 0) { // check for EOF ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ receive message failed because peer was closed", mName.c_str()); "channel '%s' ~ receive message failed because peer was closed", name.c_str()); return DEAD_OBJECT; } if (!msg->isValid(nRead)) { ALOGE("channel '%s' ~ received invalid message of size %zd", mName.c_str(), nRead); ALOGE("channel '%s' ~ received invalid message of size %zd", name.c_str(), nRead); return BAD_VALUE; } ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ received message of type %s", mName.c_str(), ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ received message of type %s", name.c_str(), ftl::enum_string(msg->header.type).c_str()); if (ATRACE_ENABLED()) { // Add an additional trace point to include data about the received message. std::string message = StringPrintf("receiveMessage(inputChannel=%s, seq=0x%" PRIx32 ", type=0x%" PRIx32 ")", mName.c_str(), msg->header.seq, msg->header.type); name.c_str(), msg->header.seq, msg->header.type); ATRACE_NAME(message.c_str()); } return OK; } bool InputChannel::probablyHasInput() const { struct pollfd pfds = {.fd = mFd, .events = POLLIN}; struct pollfd pfds = {.fd = fd.get(), .events = POLLIN}; if (::poll(&pfds, /*nfds=*/1, /*timeout=*/0) <= 0) { // This can be a false negative because EINTR and ENOMEM are not handled. The latter should // be extremely rare. The EINTR is also unlikely because it happens only when the signal Loading @@ -538,7 +561,7 @@ void InputChannel::waitForMessage(std::chrono::milliseconds timeout) const { if (timeout < 0ms) { LOG(FATAL) << "Timeout cannot be negative, received " << timeout.count(); } struct pollfd pfds = {.fd = mFd, .events = POLLIN}; struct pollfd pfds = {.fd = fd.get(), .events = POLLIN}; int ret; std::chrono::time_point<std::chrono::steady_clock> stopTime = std::chrono::steady_clock::now() + timeout; Loading @@ -551,53 +574,18 @@ void InputChannel::waitForMessage(std::chrono::milliseconds timeout) const { } std::unique_ptr<InputChannel> InputChannel::dup() const { base::unique_fd newFd(dupFd()); base::unique_fd newFd(dupChannelFd(fd.get())); 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 { if (parcel == nullptr) { ALOGE("%s: Null parcel", __func__); return BAD_VALUE; } return parcel->writeStrongBinder(mToken) ?: parcel->writeUtf8AsUtf16(mName) ?: parcel->writeUniqueFileDescriptor(mFd); } status_t InputChannel::readFromParcel(const android::Parcel* parcel) { if (parcel == nullptr) { ALOGE("%s: Null parcel", __func__); return BAD_VALUE; } mToken = parcel->readStrongBinder(); return parcel->readUtf8FromUtf16(&mName) ?: parcel->readUniqueFileDescriptor(&mFd); void InputChannel::copyTo(android::os::InputChannelCore& outChannel) const { outChannel.name = getName(); outChannel.fd.reset(dupChannelFd(fd.get())); outChannel.token = getConnectionToken(); } sp<IBinder> InputChannel::getConnectionToken() const { return mToken; } base::unique_fd InputChannel::dupFd() const { base::unique_fd newFd(::dup(getFd().get())); 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; return token; } // --- InputPublisher --- Loading libs/input/android/os/IInputFlinger.aidl +2 −3 Original line number Diff line number Diff line Loading @@ -16,14 +16,13 @@ package android.os; import android.InputChannel; import android.os.InputChannelCore; import android.gui.FocusRequest; import android.gui.WindowInfo; /** @hide */ interface IInputFlinger { InputChannel createInputChannel(in @utf8InCpp String name); InputChannelCore createInputChannel(in @utf8InCpp String name); void removeInputChannel(in IBinder connectionToken); /** * Sets focus to the window identified by the token. This must be called Loading Loading
include/input/InputTransport.h +12 −36 Original line number Diff line number Diff line Loading @@ -35,18 +35,16 @@ #include <android-base/result.h> #include <android-base/unique_fd.h> #include <android/os/InputChannelCore.h> #include <binder/IBinder.h> #include <binder/Parcelable.h> #include <input/Input.h> #include <input/InputVerifier.h> #include <sys/stat.h> #include <ui/Transform.h> #include <utils/BitSet.h> #include <utils/Errors.h> #include <utils/RefBase.h> #include <utils/Timers.h> namespace android { class Parcel; Loading Loading @@ -231,18 +229,15 @@ struct InputMessage { * input messages across processes. Each channel has a descriptive name for debugging purposes. * * Each endpoint has its own InputChannel object that specifies its file descriptor. * For parceling, this relies on android::os::InputChannelCore, defined in aidl. * * The input channel is closed when all references to it are released. */ class InputChannel : public Parcelable { class InputChannel : private android::os::InputChannelCore { public: static std::unique_ptr<InputChannel> create(const std::string& name, android::base::unique_fd fd, sp<IBinder> token); InputChannel() = default; InputChannel(const InputChannel& other) : mName(other.mName), mFd(other.dupFd()), mToken(other.mToken){}; InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token); ~InputChannel() override; static std::unique_ptr<InputChannel> create(android::os::InputChannelCore&& parceledChannel); ~InputChannel(); /** * Create a pair of input channels. * The two returned input channels are equivalent, and are labeled as "server" and "client" Loading @@ -254,9 +249,8 @@ public: std::unique_ptr<InputChannel>& outServerChannel, std::unique_ptr<InputChannel>& outClientChannel); inline std::string getName() const { return mName; } inline const android::base::unique_fd& getFd() const { return mFd; } inline sp<IBinder> getToken() const { return mToken; } inline std::string getName() const { return name; } inline int getFd() const { return fd.get(); } /* Send a message to the other endpoint. * Loading Loading @@ -304,10 +298,7 @@ public: /* Return a new object that has a duplicate of this channel's fd. */ std::unique_ptr<InputChannel> dup() const; void copyTo(InputChannel& outChannel) const; status_t readFromParcel(const android::Parcel* parcel) override; status_t writeToParcel(android::Parcel* parcel) const override; void copyTo(android::os::InputChannelCore& outChannel) const; /** * The connection token is used to identify the input connection, i.e. Loading @@ -323,26 +314,11 @@ public: */ sp<IBinder> getConnectionToken() const; bool operator==(const InputChannel& inputChannel) const { struct stat lhs, rhs; if (fstat(mFd.get(), &lhs) != 0) { return false; } if (fstat(inputChannel.getFd().get(), &rhs) != 0) { return false; } // If file descriptors are pointing to same inode they are duplicated fds. return inputChannel.getName() == getName() && inputChannel.getConnectionToken() == mToken && lhs.st_ino == rhs.st_ino; } private: base::unique_fd dupFd() const; std::string mName; base::unique_fd mFd; static std::unique_ptr<InputChannel> create(const std::string& name, android::base::unique_fd fd, sp<IBinder> token); sp<IBinder> mToken; InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token); }; /* Loading
libs/gui/tests/EndToEndNativeInputTest.cpp +8 −4 Original line number Diff line number Diff line Loading @@ -63,8 +63,7 @@ namespace android::test { using Transaction = SurfaceComposerClient::Transaction; sp<IInputFlinger> getInputFlinger() { sp<IBinder> input(defaultServiceManager()->getService( String16("inputflinger"))); sp<IBinder> input(defaultServiceManager()->waitForService(String16("inputflinger"))); if (input == nullptr) { ALOGE("Failed to link to input service"); } else { ALOGE("Linked to input"); } Loading Loading @@ -104,8 +103,13 @@ public: if (noInputChannel) { mInputInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, true); } else { mClientChannel = std::make_shared<InputChannel>(); mInputFlinger->createInputChannel("testchannels", mClientChannel.get()); android::os::InputChannelCore tempChannel; android::binder::Status result = mInputFlinger->createInputChannel("testchannels", &tempChannel); if (!result.isOk()) { ADD_FAILURE() << "binder call to createInputChannel failed"; } mClientChannel = InputChannel::create(std::move(tempChannel)); mInputInfo.token = mClientChannel->getConnectionToken(); mInputConsumer = new InputConsumer(mClientChannel); } Loading
libs/input/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -175,6 +175,7 @@ cc_library { ], srcs: [ "android/os/IInputFlinger.aidl", "android/os/InputChannelCore.aidl", "AccelerationCurve.cpp", "Input.cpp", "InputDevice.cpp", Loading
libs/input/InputTransport.cpp +46 −58 Original line number Diff line number Diff line Loading @@ -95,6 +95,21 @@ bool debugResampling() { return __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Resampling", ANDROID_LOG_INFO); } android::base::unique_fd dupChannelFd(int fd) { android::base::unique_fd newFd(::dup(fd)); if (!newFd.ok()) { ALOGE("Could not duplicate fd %i : %s", fd, 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"); return {}; } return newFd; } } // namespace using android::base::Result; Loading Loading @@ -395,15 +410,23 @@ std::unique_ptr<InputChannel> InputChannel::create(const std::string& name, return std::unique_ptr<InputChannel>(new InputChannel(name, std::move(fd), token)); } InputChannel::InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token) : mName(std::move(name)), mFd(std::move(fd)), mToken(std::move(token)) { std::unique_ptr<InputChannel> InputChannel::create( android::os::InputChannelCore&& parceledChannel) { return InputChannel::create(parceledChannel.name, parceledChannel.fd.release(), parceledChannel.token); } InputChannel::InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token) { this->name = std::move(name); this->fd.reset(std::move(fd)); this->token = std::move(token); ALOGD_IF(DEBUG_CHANNEL_LIFECYCLE, "Input channel constructed: name='%s', fd=%d", getName().c_str(), getFd().get()); getName().c_str(), getFd()); } InputChannel::~InputChannel() { ALOGD_IF(DEBUG_CHANNEL_LIFECYCLE, "Input channel destroyed: name='%s', fd=%d", getName().c_str(), getFd().get()); getName().c_str(), getFd()); } status_t InputChannel::openInputChannelPair(const std::string& name, Loading Loading @@ -441,19 +464,19 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { ATRACE_NAME_IF(ATRACE_ENABLED(), StringPrintf("sendMessage(inputChannel=%s, seq=0x%" PRIx32 ", type=0x%" PRIx32 ")", mName.c_str(), msg->header.seq, msg->header.type)); name.c_str(), msg->header.seq, msg->header.type)); const size_t msgLength = msg->size(); InputMessage cleanMsg; msg->getSanitizedCopy(&cleanMsg); ssize_t nWrite; do { nWrite = ::send(getFd().get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); } while (nWrite == -1 && errno == EINTR); if (nWrite < 0) { int error = errno; ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ error sending message of type %s, %s", mName.c_str(), ftl::enum_string(msg->header.type).c_str(), strerror(error)); name.c_str(), ftl::enum_string(msg->header.type).c_str(), strerror(error)); if (error == EAGAIN || error == EWOULDBLOCK) { return WOULD_BLOCK; } Loading @@ -465,12 +488,12 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { if (size_t(nWrite) != msgLength) { ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ error sending message type %s, send was incomplete", mName.c_str(), "channel '%s' ~ error sending message type %s, send was incomplete", name.c_str(), ftl::enum_string(msg->header.type).c_str()); return DEAD_OBJECT; } ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ sent message of type %s", mName.c_str(), ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ sent message of type %s", name.c_str(), ftl::enum_string(msg->header.type).c_str()); return OK; Loading @@ -479,13 +502,13 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { status_t InputChannel::receiveMessage(InputMessage* msg) { ssize_t nRead; do { nRead = ::recv(getFd().get(), msg, sizeof(InputMessage), MSG_DONTWAIT); nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT); } while (nRead == -1 && errno == EINTR); if (nRead < 0) { int error = errno; ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ receive message failed, errno=%d", mName.c_str(), errno); name.c_str(), errno); if (error == EAGAIN || error == EWOULDBLOCK) { return WOULD_BLOCK; } Loading @@ -497,29 +520,29 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { if (nRead == 0) { // check for EOF ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ receive message failed because peer was closed", mName.c_str()); "channel '%s' ~ receive message failed because peer was closed", name.c_str()); return DEAD_OBJECT; } if (!msg->isValid(nRead)) { ALOGE("channel '%s' ~ received invalid message of size %zd", mName.c_str(), nRead); ALOGE("channel '%s' ~ received invalid message of size %zd", name.c_str(), nRead); return BAD_VALUE; } ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ received message of type %s", mName.c_str(), ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ received message of type %s", name.c_str(), ftl::enum_string(msg->header.type).c_str()); if (ATRACE_ENABLED()) { // Add an additional trace point to include data about the received message. std::string message = StringPrintf("receiveMessage(inputChannel=%s, seq=0x%" PRIx32 ", type=0x%" PRIx32 ")", mName.c_str(), msg->header.seq, msg->header.type); name.c_str(), msg->header.seq, msg->header.type); ATRACE_NAME(message.c_str()); } return OK; } bool InputChannel::probablyHasInput() const { struct pollfd pfds = {.fd = mFd, .events = POLLIN}; struct pollfd pfds = {.fd = fd.get(), .events = POLLIN}; if (::poll(&pfds, /*nfds=*/1, /*timeout=*/0) <= 0) { // This can be a false negative because EINTR and ENOMEM are not handled. The latter should // be extremely rare. The EINTR is also unlikely because it happens only when the signal Loading @@ -538,7 +561,7 @@ void InputChannel::waitForMessage(std::chrono::milliseconds timeout) const { if (timeout < 0ms) { LOG(FATAL) << "Timeout cannot be negative, received " << timeout.count(); } struct pollfd pfds = {.fd = mFd, .events = POLLIN}; struct pollfd pfds = {.fd = fd.get(), .events = POLLIN}; int ret; std::chrono::time_point<std::chrono::steady_clock> stopTime = std::chrono::steady_clock::now() + timeout; Loading @@ -551,53 +574,18 @@ void InputChannel::waitForMessage(std::chrono::milliseconds timeout) const { } std::unique_ptr<InputChannel> InputChannel::dup() const { base::unique_fd newFd(dupFd()); base::unique_fd newFd(dupChannelFd(fd.get())); 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 { if (parcel == nullptr) { ALOGE("%s: Null parcel", __func__); return BAD_VALUE; } return parcel->writeStrongBinder(mToken) ?: parcel->writeUtf8AsUtf16(mName) ?: parcel->writeUniqueFileDescriptor(mFd); } status_t InputChannel::readFromParcel(const android::Parcel* parcel) { if (parcel == nullptr) { ALOGE("%s: Null parcel", __func__); return BAD_VALUE; } mToken = parcel->readStrongBinder(); return parcel->readUtf8FromUtf16(&mName) ?: parcel->readUniqueFileDescriptor(&mFd); void InputChannel::copyTo(android::os::InputChannelCore& outChannel) const { outChannel.name = getName(); outChannel.fd.reset(dupChannelFd(fd.get())); outChannel.token = getConnectionToken(); } sp<IBinder> InputChannel::getConnectionToken() const { return mToken; } base::unique_fd InputChannel::dupFd() const { base::unique_fd newFd(::dup(getFd().get())); 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; return token; } // --- InputPublisher --- Loading
libs/input/android/os/IInputFlinger.aidl +2 −3 Original line number Diff line number Diff line Loading @@ -16,14 +16,13 @@ package android.os; import android.InputChannel; import android.os.InputChannelCore; import android.gui.FocusRequest; import android.gui.WindowInfo; /** @hide */ interface IInputFlinger { InputChannel createInputChannel(in @utf8InCpp String name); InputChannelCore createInputChannel(in @utf8InCpp String name); void removeInputChannel(in IBinder connectionToken); /** * Sets focus to the window identified by the token. This must be called Loading