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

Commit 28efc19d authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Reland "Let InputReader handle its own thread"

This CL was first landed in Ic732436d4f00a831e317be1f16ac106a11652cff
but was reverted due to flaky tests.

The flaky tests were caused by races between the instrumented test
classes and the InputReader class under test, which now runs in a new
thread.

In addition to re-landing the change, this CL ensures that InputReader
does not start its own thread in its unit tests, but instead keep using
the loopOnce method that is exposed for testing.

Bug: 130819454
Test: atest inputflinger_tests
Test: Touch input works on crosshatch
Change-Id: I5bbfc68b6be6745efc8b7106a9292ee3cb431c9c
parent cace66c5
Loading
Loading
Loading
Loading
+4 −5
Original line number Original line Diff line number Diff line
@@ -46,7 +46,6 @@ InputManager::~InputManager() {
}
}


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


@@ -57,9 +56,9 @@ status_t InputManager::start() {
        return result;
        return result;
    }
    }


    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    result = mReader->start();
    if (result) {
    if (result) {
        ALOGE("Could not start InputReader thread due to error %d.", result);
        ALOGE("Could not start InputReader due to error %d.", result);


        mDispatcherThread->requestExit();
        mDispatcherThread->requestExit();
        return result;
        return result;
@@ -69,9 +68,9 @@ status_t InputManager::start() {
}
}


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


    result = mDispatcherThread->requestExitAndWait();
    result = mDispatcherThread->requestExitAndWait();
+5 −6
Original line number Original line Diff line number Diff line
@@ -43,15 +43,15 @@ class InputDispatcherThread;
/*
/*
 * The input manager is the core of the system event processing.
 * The input manager is the core of the system event processing.
 *
 *
 * The input manager uses two threads.
 * The input manager has two components.
 *
 *
 * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events,
 * 1. The InputReader class starts a thread that reads and preprocesses raw input events, applies
 *    applies policy, and posts messages to a queue managed by the DispatcherThread.
 *    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 InputDispatcherThread (called "InputDispatcher") thread waits for new events on the
 *    queue and asynchronously dispatches them to applications.
 *    queue and asynchronously dispatches them to applications.
 *
 *
 * By design, the InputReaderThread class and InputDispatcherThread class do not share any
 * By design, the InputReader class and InputDispatcherThread class do not share any
 * internal state.  Moreover, all communication is done one way from the InputReaderThread
 * 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
 * into the InputDispatcherThread and never the reverse.  Both classes may interact with the
 * InputDispatchPolicy, however.
 * InputDispatchPolicy, however.
 *
 *
@@ -102,7 +102,6 @@ public:


private:
private:
    sp<InputReaderInterface> mReader;
    sp<InputReaderInterface> mReader;
    sp<InputReaderThread> mReaderThread;


    sp<InputClassifierInterface> mClassifier;
    sp<InputClassifierInterface> mClassifier;


+0 −14
Original line number Original line Diff line number Diff line
@@ -33,20 +33,6 @@ using android::base::StringPrintf;


namespace android {
namespace android {


// --- InputReaderThread ---

InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
        Thread(/*canCallJava*/ true), mReader(reader) {
}

InputReaderThread::~InputReaderThread() {
}

bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

// --- InputReaderConfiguration ---
// --- InputReaderConfiguration ---


std::string InputReaderConfiguration::changesToString(uint32_t changes) {
std::string InputReaderConfiguration::changesToString(uint32_t changes) {
+25 −23
Original line number Original line Diff line number Diff line
@@ -19,12 +19,12 @@


#include "PointerControllerInterface.h"
#include "PointerControllerInterface.h"


#include <input/DisplayViewport.h>
#include <input/Input.h>
#include <input/Input.h>
#include <input/InputDevice.h>
#include <input/InputDevice.h>
#include <input/DisplayViewport.h>
#include <input/VelocityControl.h>
#include <input/VelocityControl.h>
#include <input/VelocityTracker.h>
#include <input/VelocityTracker.h>
#include <utils/Thread.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/RefBase.h>


#include <stddef.h>
#include <stddef.h>
@@ -44,7 +44,16 @@


namespace android {
namespace android {


/* Processes raw input events and sends cooked event data to an input listener. */
// --- InputReaderInterface ---

/* The interface for the InputReader shared library.
 *
 * Manages one or more threads that process raw input events and sends cooked event data to an
 * input listener.
 *
 * The implementation must guarantee thread safety for this interface. However, since the input
 * listener is NOT thread safe, all calls to the listener must happen from the same thread.
 */
class InputReaderInterface : public virtual RefBase {
class InputReaderInterface : public virtual RefBase {
protected:
protected:
    InputReaderInterface() { }
    InputReaderInterface() { }
@@ -56,18 +65,17 @@ public:
     * This method may be called on any thread (usually by the input manager). */
     * This method may be called on any thread (usually by the input manager). */
    virtual void dump(std::string& dump) = 0;
    virtual void dump(std::string& dump) = 0;


    /* Called by the heatbeat to ensures that the reader has not deadlocked. */
    /* Called by the heartbeat to ensures that the reader has not deadlocked. */
    virtual void monitor() = 0;
    virtual void monitor() = 0;


    /* Returns true if the input device is enabled. */
    /* Returns true if the input device is enabled. */
    virtual bool isInputDeviceEnabled(int32_t deviceId) = 0;
    virtual bool isInputDeviceEnabled(int32_t deviceId) = 0;


    /* Runs a single iteration of the processing loop.
    /* Makes the reader start processing events from the kernel. */
     * Nominally reads and processes one incoming message from the EventHub.
    virtual status_t start() = 0;
     *

     * This method should be called on the input reader thread.
    /* Makes the reader stop processing any more events. */
     */
    virtual status_t stop() = 0;
    virtual void loopOnce() = 0;


    /* Gets information about all input devices.
    /* Gets information about all input devices.
     *
     *
@@ -104,17 +112,7 @@ public:
    virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0;
    virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0;
};
};


/* Reads raw events from the event hub and processes them, endlessly. */
// --- InputReaderConfiguration ---
class InputReaderThread : public Thread {
public:
    explicit InputReaderThread(const sp<InputReaderInterface>& reader);
    virtual ~InputReaderThread();

private:
    sp<InputReaderInterface> mReader;

    virtual bool threadLoop();
};


/*
/*
 * Input reader configuration.
 * Input reader configuration.
@@ -285,6 +283,8 @@ private:
    std::vector<DisplayViewport> mDisplays;
    std::vector<DisplayViewport> mDisplays;
};
};


// --- TouchAffineTransformation ---

struct TouchAffineTransformation {
struct TouchAffineTransformation {
    float x_scale;
    float x_scale;
    float x_ymix;
    float x_ymix;
@@ -307,6 +307,8 @@ struct TouchAffineTransformation {
    void applyTo(float& x, float& y) const;
    void applyTo(float& x, float& y) const;
};
};


// --- InputReaderPolicyInterface ---

/*
/*
 * Input reader policy interface.
 * Input reader policy interface.
 *
 *
@@ -316,8 +318,8 @@ struct TouchAffineTransformation {
 * The actual implementation is partially supported by callbacks into the DVM
 * The actual implementation is partially supported by callbacks into the DVM
 * via JNI.  This interface is also mocked in the unit tests.
 * via JNI.  This interface is also mocked in the unit tests.
 *
 *
 * These methods must NOT re-enter the input reader since they may be called while
 * These methods will NOT re-enter the input reader interface, so they may be called from
 * holding the input reader lock.
 * any method in the input reader interface.
 */
 */
class InputReaderPolicyInterface : public virtual RefBase {
class InputReaderPolicyInterface : public virtual RefBase {
protected:
protected:
+46 −1
Original line number Original line Diff line number Diff line
@@ -38,16 +38,38 @@
#include <unistd.h>
#include <unistd.h>


#include <log/log.h>
#include <log/log.h>
#include <utils/Errors.h>


#include <android-base/stringprintf.h>
#include <android-base/stringprintf.h>
#include <input/Keyboard.h>
#include <input/Keyboard.h>
#include <input/VirtualKeyMap.h>
#include <input/VirtualKeyMap.h>

#include <utils/Thread.h>


using android::base::StringPrintf;
using android::base::StringPrintf;


namespace android {
namespace android {


// --- InputReader::InputReaderThread ---

/* Thread that reads raw events from the event hub and processes them, endlessly. */
class InputReader::InputReaderThread : public Thread {
public:
    explicit InputReaderThread(InputReader* reader)
          : Thread(/* canCallJava */ true), mReader(reader) {}

    ~InputReaderThread() {}

private:
    InputReader* mReader;

    bool threadLoop() override {
        mReader->loopOnce();
        return true;
    }
};

// --- InputReader ---

InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
                         const sp<InputReaderPolicyInterface>& policy,
                         const sp<InputReaderPolicyInterface>& policy,
                         const sp<InputListenerInterface>& listener)
                         const sp<InputListenerInterface>& listener)
@@ -61,6 +83,7 @@ InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
        mNextTimeout(LLONG_MAX),
        mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
        mConfigurationChangesToRefresh(0) {
    mQueuedListener = new QueuedInputListener(listener);
    mQueuedListener = new QueuedInputListener(listener);
    mThread = new InputReaderThread(this);


    { // acquire lock
    { // acquire lock
        AutoMutex _l(mLock);
        AutoMutex _l(mLock);
@@ -76,6 +99,28 @@ InputReader::~InputReader() {
    }
    }
}
}


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

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

void InputReader::loopOnce() {
void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t oldGeneration;
    int32_t timeoutMillis;
    int32_t timeoutMillis;
Loading