Add input system to Watchdog.
Bug: 5094994
Change-Id: I153866958efc64ac19bda8b997c1c9f6ad425ec4
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 0a567fd..960e414 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -1294,4 +1294,11 @@
} // release lock
}
+void EventHub::monitor() {
+ // Acquire and release the lock to ensure that the event hub has not deadlocked.
+ mLock.lock();
+ mLock.unlock();
+}
+
+
}; // namespace android
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 08f73ca..fae5d4f 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -208,7 +208,11 @@
/* Wakes up getEvents() if it is blocked on a read. */
virtual void wake() = 0;
+ /* Dump EventHub state to a string. */
virtual void dump(String8& dump) = 0;
+
+ /* Called by the heatbeat to ensures that the reader has not deadlocked. */
+ virtual void monitor() = 0;
};
class EventHub : public EventHubInterface
@@ -259,6 +263,7 @@
virtual void wake();
virtual void dump(String8& dump);
+ virtual void monitor();
protected:
virtual ~EventHub();
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index ce9e14f..22372cf1 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -3919,6 +3919,8 @@
}
void InputDispatcher::dump(String8& dump) {
+ AutoMutex _l(mLock);
+
dump.append("Input Dispatcher State:\n");
dumpDispatchStateLocked(dump);
@@ -3928,6 +3930,12 @@
dump.appendFormat(INDENT2 "KeyRepeatTimeout: %0.1fms\n", mConfig.keyRepeatTimeout * 0.000001f);
}
+void InputDispatcher::monitor() {
+ // Acquire and release the lock to ensure that the dispatcher has not deadlocked.
+ mLock.lock();
+ mLock.unlock();
+}
+
// --- InputDispatcher::Queue ---
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 01c7b35..cae1610 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -282,6 +282,9 @@
* This method may be called on any thread (usually by the input manager). */
virtual void dump(String8& dump) = 0;
+ /* Called by the heatbeat to ensures that the dispatcher has not deadlocked. */
+ virtual void monitor() = 0;
+
/* Runs a single iteration of the dispatch loop.
* Nominally processes one queued event, a timeout, or a response from an input consumer.
*
@@ -370,6 +373,7 @@
explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
virtual void dump(String8& dump);
+ virtual void monitor();
virtual void dispatchOnce();
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index dacc73f..2eacbeb 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -731,6 +731,15 @@
mConfig.pointerGestureZoomSpeedRatio);
}
+void InputReader::monitor() {
+ // Acquire and release the lock to ensure that the reader has not deadlocked.
+ mLock.lock();
+ mLock.unlock();
+
+ // Check the EventHub
+ mEventHub->monitor();
+}
+
// --- InputReader::ContextImpl ---
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index e82c4e7..e9daef5 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -210,6 +210,9 @@
* This method may be called on any thread (usually by the input manager). */
virtual void dump(String8& dump) = 0;
+ /* Called by the heatbeat to ensures that the reader has not deadlocked. */
+ virtual void monitor() = 0;
+
/* Runs a single iteration of the processing loop.
* Nominally reads and processes one incoming message from the EventHub.
*
@@ -297,6 +300,7 @@
virtual ~InputReader();
virtual void dump(String8& dump);
+ virtual void monitor();
virtual void loopOnce();
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 4a866a8..87f212b 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -631,6 +631,9 @@
virtual void dump(String8& dump) {
}
+ virtual void monitor() {
+ }
+
virtual void requestReopenDevices() {
}
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index 1d0857b..c8b18c8 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import com.android.internal.util.XmlUtils;
+import com.android.server.Watchdog;
import org.xmlpull.v1.XmlPullParser;
@@ -52,7 +53,7 @@
/*
* Wraps the C++ InputManager and provides its callbacks.
*/
-public class InputManager {
+public class InputManager implements Watchdog.Monitor {
static final String TAG = "InputManager";
private static final boolean DEBUG = false;
@@ -94,6 +95,7 @@
InputChannel toChannel);
private static native void nativeSetPointerSpeed(int speed);
private static native String nativeDump();
+ private static native void nativeMonitor();
// Input event injection constants defined in InputDispatcher.h.
static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -135,6 +137,9 @@
Slog.i(TAG, "Initializing input manager");
nativeInit(mContext, mCallbacks, looper.getQueue());
+
+ // Add ourself to the Watchdog monitors.
+ Watchdog.getInstance().addMonitor(this);
}
public void start() {
@@ -456,6 +461,12 @@
}
}
+ // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
+ public void monitor() {
+ synchronized (mInputFilterLock) { }
+ nativeMonitor();
+ }
+
private final class InputFilterHost implements InputFilter.Host {
private boolean mDisconnected;
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 3414eea..7c84e43 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -1288,6 +1288,15 @@
return env->NewStringUTF(dump.string());
}
+static void android_server_InputManager_nativeMonitor(JNIEnv* env, jclass clazz) {
+ if (checkInputManagerUnitialized(env)) {
+ return;
+ }
+
+ gNativeInputManager->getInputManager()->getReader()->monitor();
+ gNativeInputManager->getInputManager()->getDispatcher()->monitor();
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gInputManagerMethods[] = {
@@ -1338,6 +1347,8 @@
(void*) android_server_InputManager_nativeSetPointerSpeed },
{ "nativeDump", "()Ljava/lang/String;",
(void*) android_server_InputManager_nativeDump },
+ { "nativeMonitor", "()V",
+ (void*) android_server_InputManager_nativeMonitor },
};
#define FIND_CLASS(var, className) \