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
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index b9bec44..dcb3ebc 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -240,6 +240,24 @@
     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 @@
     mKeyRepeatState.lastKeyEntry = nullptr;
 
     policy->getDispatcherConfiguration(&mConfig);
+
+    mThread = new InputDispatcherThread(this);
 }
 
 InputDispatcher::~InputDispatcher() {
@@ -281,6 +301,28 @@
     }
 }
 
+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