Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1560166e authored by Garfield Tan's avatar Garfield Tan
Browse files

Second reland "Let InputFlinger create the server InputChannel"

Bug: 167947395
Bug: 169173706
Test: atest NexusLauncherTests:com.android.launcher3.ui.TaplTestsLauncher3
Change-Id: I9cbe8ce92d006abfe9246f88844730951caf940b
parent 062c8574
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -246,6 +246,8 @@ 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;

@@ -277,6 +279,8 @@ public:
    }

private:
    base::unique_fd dupFd() const;

    std::string mName;
    android::base::unique_fd mFd;

+4 −7
Original line number Diff line number Diff line
@@ -68,12 +68,10 @@ class InputSurface {
public:
    InputSurface(const sp<SurfaceControl> &sc, int width, int height) {
        mSurfaceControl = sc;
        std::unique_ptr<InputChannel> clientChannel;
        InputChannel::openInputChannelPair("testchannels", mServerChannel, clientChannel);
        mClientChannel = std::move(clientChannel);

        mInputFlinger = getInputFlinger();
        mInputFlinger->registerInputChannel(*mServerChannel);
        mClientChannel = std::make_shared<InputChannel>();
        mInputFlinger->createInputChannel("testchannels", mClientChannel.get());

        populateInputInfo(width, height);

@@ -155,7 +153,7 @@ public:
        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&,
                    const sp<SurfaceControl>&)> transactionBody) {
@@ -192,7 +190,7 @@ private:
    }

    void populateInputInfo(int width, int height) {
        mInputInfo.token = mServerChannel->getConnectionToken();
        mInputInfo.token = mClientChannel->getConnectionToken();
        mInputInfo.name = "Test info";
        mInputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL;
        mInputInfo.type = InputWindowInfo::Type::BASE_APPLICATION;
@@ -219,7 +217,6 @@ private:
    }
public:
    sp<SurfaceControl> mSurfaceControl;
    std::unique_ptr<InputChannel> mServerChannel;
    std::shared_ptr<InputChannel> mClientChannel;
    sp<IInputFlinger> mInputFlinger;

+24 −13
Original line number Diff line number Diff line
@@ -377,22 +377,16 @@ status_t InputChannel::receiveMessage(InputMessage* msg) {
}

std::unique_ptr<InputChannel> InputChannel::dup() 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 nullptr;
    }
    base::unique_fd newFd(dupFd());
    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__);
@@ -415,6 +409,23 @@ sp<IBinder> InputChannel::getConnectionToken() const {
    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(const std::shared_ptr<InputChannel>& channel) : mChannel(channel) {}
+2 −2
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@ interface IInputFlinger
    // shouldn't be a concern.
    oneway void setInputWindows(in InputWindowInfo[] inputHandles,
            in @nullable ISetInputWindowsListener setInputWindowsListener);
    void registerInputChannel(in InputChannel channel);
    void unregisterInputChannel(in IBinder connectionToken);
    InputChannel createInputChannel(in @utf8InCpp String name);
    void removeInputChannel(in IBinder connectionToken);
    /**
     * Sets focus to the window identified by the token. This must be called
     * after updating any input window handles.
+28 −4
Original line number Diff line number Diff line
@@ -31,6 +31,25 @@

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(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
@@ -119,7 +138,7 @@ binder::Status InputManager::setInputWindows(
}

// 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();
    const int uid = ipc->getCallingUid();
    if (uid != AID_SHELL && uid != AID_ROOT) {
@@ -128,12 +147,17 @@ binder::Status InputManager::registerInputChannel(const InputChannel& channel) {
        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();
}

binder::Status InputManager::unregisterInputChannel(const sp<IBinder>& connectionToken) {
    mDispatcher->unregisterInputChannel(connectionToken);
binder::Status InputManager::removeInputChannel(const sp<IBinder>& connectionToken) {
    mDispatcher->removeInputChannel(connectionToken);
    return binder::Status::ok();
}

Loading