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

Commit 3608aadd authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Let InputDispatcher handle its own thread

We move the threading logic from InputManger to InputDispatcher by
removing dispatchOnce() method from InputDispatcherInterface and adding
a start() and stop() method in its place.

Bug: 130819454
Test: atest inputflinger_tests
Test: Touch input works on crosshatch
Change-Id: I1d06be2330a2f8b9261fd5c5323a486d6aa544e8
parent 28efc19d
Loading
Loading
Loading
Loading
+8 −10
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@

#include "InputManager.h"
#include "InputDispatcherFactory.h"
#include "InputDispatcherThread.h"
#include "InputReaderFactory.h"

#include <binder/IPCThreadState.h>
@@ -38,19 +37,14 @@ InputManager::InputManager(
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    mClassifier = new InputClassifier(mDispatcher);
    mReader = createInputReader(readerPolicy, mClassifier);
    initialize();
}

InputManager::~InputManager() {
    stop();
}

void InputManager::initialize() {
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    status_t result = mDispatcher->start();
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
@@ -60,7 +54,7 @@ status_t InputManager::start() {
    if (result) {
        ALOGE("Could not start InputReader due to error %d.", result);

        mDispatcherThread->requestExit();
        mDispatcher->stop();
        return result;
    }

@@ -68,17 +62,21 @@ status_t InputManager::start() {
}

status_t InputManager::stop() {
    status_t status = OK;

    status_t result = mReader->stop();
    if (result) {
        ALOGW("Could not stop InputReader due to error %d.", result);
        status = result;
    }

    result = mDispatcherThread->requestExitAndWait();
    result = mDispatcher->stop();
    if (result) {
        ALOGW("Could not stop InputDispatcher thread due to error %d.", result);
        status = result;
    }

    return OK;
    return status;
}

sp<InputReaderInterface> InputManager::getReader() {
+4 −7
Original line number Diff line number Diff line
@@ -47,10 +47,10 @@ class InputDispatcherThread;
 *
 * 1. The InputReader class starts a thread that reads and preprocesses raw input events, applies
 *    policy, and posts messages to a queue managed by the InputDispatcherThread.
 * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the
 * 2. The InputDispatcher class starts a thread that waits for new events on the
 *    queue and asynchronously dispatches them to applications.
 *
 * By design, the InputReader class and InputDispatcherThread class do not share any
 * By design, the InputReader class and InputDispatcher class do not share any
 * internal state.  Moreover, all communication is done one way from the InputReader
 * into the InputDispatcherThread and never the reverse.  Both classes may interact with the
 * InputDispatchPolicy, however.
@@ -65,10 +65,10 @@ protected:
    virtual ~InputManagerInterface() { }

public:
    /* Starts the input manager threads. */
    /* Starts the input threads. */
    virtual status_t start() = 0;

    /* Stops the input manager threads and waits for them to exit. */
    /* Stops the input threads and waits for them to exit. */
    virtual status_t stop() = 0;

    /* Gets the input reader. */
@@ -106,9 +106,6 @@ private:
    sp<InputClassifierInterface> mClassifier;

    sp<InputDispatcherInterface> mDispatcher;
    sp<InputDispatcherThread> mDispatcherThread;

    void initialize();
};

} // namespace android
+0 −1
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ cc_library_static {
        "InjectionState.cpp",
        "InputDispatcher.cpp",
        "InputDispatcherFactory.cpp",
        "InputDispatcherThread.cpp",
        "InputState.cpp",
        "InputTarget.cpp",
        "Monitor.cpp",
+42 −0
Original line number Diff line number Diff line
@@ -240,6 +240,24 @@ static bool removeByValue(std::unordered_map<K, V>& map, const V& value) {
    return removed;
}

// --- InputDispatcherThread ---

class InputDispatcher::InputDispatcherThread : public Thread {
public:
    explicit InputDispatcherThread(InputDispatcher* dispatcher)
          : Thread(/* canCallJava */ true), mDispatcher(dispatcher) {}

    ~InputDispatcherThread() {}

private:
    InputDispatcher* mDispatcher;

    virtual bool threadLoop() override {
        mDispatcher->dispatchOnce();
        return true;
    }
};

// --- InputDispatcher ---

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
@@ -264,6 +282,8 @@ InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& polic
    mKeyRepeatState.lastKeyEntry = nullptr;

    policy->getDispatcherConfiguration(&mConfig);

    mThread = new InputDispatcherThread(this);
}

InputDispatcher::~InputDispatcher() {
@@ -281,6 +301,28 @@ InputDispatcher::~InputDispatcher() {
    }
}

status_t InputDispatcher::start() {
    if (mThread->isRunning()) {
        return ALREADY_EXISTS;
    }
    return mThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
}

status_t InputDispatcher::stop() {
    if (!mThread->isRunning()) {
        return OK;
    }
    if (gettid() == mThread->getTid()) {
        ALOGE("InputDispatcher can only be stopped from outside of the InputDispatcherThread!");
        return INVALID_OPERATION;
    }
    // Directly calling requestExitAndWait() causes the thread to not exit
    // if mLooper is waiting for a long timeout.
    mThread->requestExit();
    mLooper->wake();
    return mThread->requestExitAndWait();
}

void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
+10 −2
Original line number Diff line number Diff line
@@ -82,8 +82,8 @@ public:
    virtual void dump(std::string& dump) override;
    virtual void monitor() override;
    virtual bool waitForIdle() override;

    virtual void dispatchOnce() override;
    virtual status_t start() override;
    virtual status_t stop() override;

    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
    virtual void notifyKey(const NotifyKeyArgs* args) override;
@@ -124,6 +124,9 @@ private:
        STALE,
    };

    class InputDispatcherThread;
    sp<InputDispatcherThread> mThread;

    sp<InputDispatcherPolicyInterface> mPolicy;
    android::InputDispatcherConfiguration mConfig;

@@ -141,6 +144,11 @@ private:

    DropReason mLastDropReason GUARDED_BY(mLock);

    // With each iteration, InputDispatcher nominally processes one queued event,
    // a timeout, or a response from an input consumer.
    // This method should only be called on the input dispatcher's own thread.
    void dispatchOnce();

    void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) REQUIRES(mLock);

    // Enqueues an inbound event.  Returns true if mLooper->wake() should be called.
Loading