Let InputReader handle its own thread
Previously, InputManager created and managed the InputReaderThread,
which interacted with InputReader through the loopOnce() method in
InputReaderInterface.
We move the threading logic from InputManager to InputReader by removing
the loopOnce() method from InputReaderInterface and adding a start() and
stop() method in its place.
Once InputReader is created, InputManager will call
InputReaderInterface::start(), which creates and starts InputReader's
own thread. InputManager can also call InputReaderInterface::stop() to
halt further processing on InputReader's thread.
Bug: 130819454
Test: atest inputflinger_tests
Test: Touch input works on crosshatch
Change-Id: Ic732436d4f00a831e317be1f16ac106a11652cff
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index e57604c..5d52bbc 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -38,16 +38,38 @@
#include <unistd.h>
#include <log/log.h>
+#include <utils/Errors.h>
#include <android-base/stringprintf.h>
#include <input/Keyboard.h>
#include <input/VirtualKeyMap.h>
-
+#include <utils/Thread.h>
using android::base::StringPrintf;
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,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener)
@@ -61,6 +83,7 @@
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
mQueuedListener = new QueuedInputListener(listener);
+ mThread = new InputReaderThread(this);
{ // acquire lock
AutoMutex _l(mLock);
@@ -76,6 +99,28 @@
}
}
+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() {
int32_t oldGeneration;
int32_t timeoutMillis;
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 7b4321e..3cf4535 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -38,12 +38,12 @@
* that it sends to the input listener. Some functions of the input reader, such as early
* event filtering in low power states, are controlled by a separate policy object.
*
- * The InputReader owns a collection of InputMappers. Most of the work it does happens
- * on the input reader thread but the InputReader can receive queries from other system
+ * The InputReader owns a collection of InputMappers. InputReader starts its own thread, where
+ * most of the work happens, but the InputReader can receive queries from other system
* components running on arbitrary threads. To keep things manageable, the InputReader
* uses a single Mutex to guard its state. The Mutex may be held while calling into the
* EventHub or the InputReaderPolicy but it is never held while calling into the
- * InputListener.
+ * InputListener. All calls to InputListener must happen from InputReader's thread.
*/
class InputReader : public InputReaderInterface {
public:
@@ -55,7 +55,8 @@
virtual void dump(std::string& dump) override;
virtual void monitor() override;
- virtual void loopOnce() override;
+ virtual status_t start() override;
+ virtual status_t stop() override;
virtual void getInputDevices(std::vector<InputDeviceInfo>& outInputDevices) override;
@@ -111,6 +112,9 @@
friend class ContextImpl;
private:
+ class InputReaderThread;
+ sp<InputReaderThread> mThread;
+
Mutex mLock;
Condition mReaderIsAliveCondition;
@@ -133,6 +137,10 @@
KeyedVector<int32_t, InputDevice*> mDevices;
+ // With each iteration of the loop, InputReader reads and processes one incoming message from
+ // the EventHub.
+ void loopOnce();
+
// low-level input event decoding and device management
void processEventsLocked(const RawEvent* rawEvents, size_t count);