Add dump to Input Classifier
Currently, the InputClassifier stage that is positioned between
InputReader and InputDispatcher is not accounted for when doing a
'dumpsys input'. But that stage may contain important information about
the operation and the InputClassifier HAL. Add the dump(..) command to
both InputClassifier and MotionClassifier.
Test: dumpsys input and inspect the resulting text
Next, crash the InputClassifier HAL (killall android.hardware.input.classifier@1.0-service
Then again 'dumpsys input' to check that the HAL status is 'not
responding'
Bug: 117935272
Change-Id: Ie7ddca2e355e094f93236a9bc667faad7a99ee70
diff --git a/services/inputflinger/BlockingQueue.h b/services/inputflinger/BlockingQueue.h
index b892120..c9eb683 100644
--- a/services/inputflinger/BlockingQueue.h
+++ b/services/inputflinger/BlockingQueue.h
@@ -80,6 +80,16 @@
mQueue.clear();
};
+ /**
+ * How many elements are currently stored in the queue.
+ * Primary used for debugging.
+ * Does not block.
+ */
+ size_t size() {
+ std::scoped_lock lock(mLock);
+ return mQueue.size();
+ }
+
private:
size_t mCapacity;
/**
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index 7ade0d4..09a004c 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -19,6 +19,7 @@
#include "InputClassifier.h"
#include <algorithm>
+#include <android-base/stringprintf.h>
#include <cmath>
#include <inttypes.h>
#include <log/log.h>
@@ -26,9 +27,17 @@
#include <pthread.h>
#endif
#include <server_configurable_flags/get_flags.h>
+#include <unordered_set>
#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
+#define INDENT1 " "
+#define INDENT2 " "
+#define INDENT3 " "
+#define INDENT4 " "
+#define INDENT5 " "
+
+using android::base::StringPrintf;
using android::hardware::hidl_bitfield;
using android::hardware::hidl_vec;
using namespace android::hardware::input;
@@ -646,6 +655,30 @@
mEvents.push(std::make_unique<NotifyDeviceResetArgs>(args));
}
+void MotionClassifier::dump(std::string& dump) {
+ std::scoped_lock lock(mLock);
+ std::string serviceStatus = mService->ping().isOk() ? "running" : " not responding";
+ dump += StringPrintf(INDENT2 "mService status: %s\n", serviceStatus.c_str());
+ dump += StringPrintf(INDENT2 "mEvents: %zu element(s) (max=%zu)\n",
+ mEvents.size(), MAX_EVENTS);
+ dump += INDENT2 "mClassifications, mLastDownTimes:\n";
+ dump += INDENT3 "Device Id\tClassification\tLast down time";
+ // Combine mClassifications and mLastDownTimes into a single table.
+ // Create a superset of device ids.
+ std::unordered_set<int32_t> deviceIds;
+ std::for_each(mClassifications.begin(), mClassifications.end(),
+ [&deviceIds](auto pair){ deviceIds.insert(pair.first); });
+ std::for_each(mLastDownTimes.begin(), mLastDownTimes.end(),
+ [&deviceIds](auto pair){ deviceIds.insert(pair.first); });
+ for(int32_t deviceId : deviceIds) {
+ const MotionClassification classification =
+ getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
+ const nsecs_t downTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
+ dump += StringPrintf("\n" INDENT4 "%" PRId32 "\t%s\t%" PRId64,
+ deviceId, motionClassificationToString(classification), downTime);
+ }
+}
+
// --- InputClassifier ---
InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener) :
@@ -694,4 +727,16 @@
mListener->notifyDeviceReset(args);
}
+void InputClassifier::dump(std::string& dump) {
+ dump += "Input Classifier State:\n";
+
+ dump += INDENT1 "Motion Classifier:\n";
+ if (mMotionClassifier) {
+ mMotionClassifier->dump(dump);
+ } else {
+ dump += INDENT2 "<nullptr>";
+ }
+ dump += "\n";
+}
+
} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index cb46494..4b9dae2 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -70,6 +70,11 @@
virtual MotionClassification classify(const NotifyMotionArgs& args) = 0;
virtual void reset() = 0;
virtual void reset(const NotifyDeviceResetArgs& args) = 0;
+
+ /**
+ * Dump the state of the motion classifier
+ */
+ virtual void dump(std::string& dump) = 0;
};
/**
@@ -77,6 +82,12 @@
* Provides classification to events.
*/
class InputClassifierInterface : public virtual RefBase, public InputListenerInterface {
+public:
+ /**
+ * Dump the state of the input classifier.
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual void dump(std::string& dump) = 0;
protected:
InputClassifierInterface() { }
virtual ~InputClassifierInterface() { }
@@ -110,6 +121,8 @@
virtual void reset() override;
virtual void reset(const NotifyDeviceResetArgs& args) override;
+ virtual void dump(std::string& dump) override;
+
private:
// The events that need to be sent to the HAL.
BlockingQueue<ClassifierEvent> mEvents;
@@ -186,6 +199,8 @@
virtual void notifySwitch(const NotifySwitchArgs* args) override;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+ virtual void dump(std::string& dump) override;
+
private:
std::unique_ptr<MotionClassifierInterface> mMotionClassifier = nullptr;
// The next stage to pass input events to
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index b3b9e3e..a7fd9ba 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -84,6 +84,10 @@
return mReader;
}
+sp<InputClassifierInterface> InputManager::getClassifier() {
+ return mClassifier;
+}
+
sp<InputDispatcherInterface> InputManager::getDispatcher() {
return mDispatcher;
}
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 142ec0c..e632da3 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -90,6 +90,7 @@
virtual status_t stop();
virtual sp<InputReaderInterface> getReader();
+ virtual sp<InputClassifierInterface> getClassifier();
virtual sp<InputDispatcherInterface> getDispatcher();
virtual void setInputWindows(const Vector<InputWindowInfo>& handles);