Limit the number of printed entries in a queue

When debugging some input bugs, it takes a while to scroll through all
of the entries in waitQueues and outboundQueues.
For example, the count can be > 100 for some ANR scenarios.

Limit the number to 50 total entries printed: 25 oldest and 25 newest.
This quantity should be sufficient to figure out what's going on with
the queues.

Note: I could not reproduce the ANR anymore, so the latest patchset was
not tested using the first test procedure.

Bug: 160561987
Test: reproduce an ANR using monkey, then look at dumpsys input
adb shell monkey 10000
adb shell dumpsys input
Test: the above procedure, but without 'reproduce ANR'

Change-Id: I01d661e0a85cc5bfbf61fa4b23689e8b27daa84b
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index 4328e03..34fa239 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -70,12 +70,6 @@
     releaseInjectionState();
 }
 
-std::string EventEntry::getDescription() const {
-    std::string result;
-    appendDescription(result);
-    return result;
-}
-
 void EventEntry::release() {
     refCount -= 1;
     if (refCount == 0) {
@@ -99,8 +93,8 @@
 
 ConfigurationChangedEntry::~ConfigurationChangedEntry() {}
 
-void ConfigurationChangedEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("ConfigurationChangedEvent(), policyFlags=0x%08x", policyFlags);
+std::string ConfigurationChangedEntry::getDescription() const {
+    return StringPrintf("ConfigurationChangedEvent(), policyFlags=0x%08x", policyFlags);
 }
 
 // --- DeviceResetEntry ---
@@ -110,8 +104,8 @@
 
 DeviceResetEntry::~DeviceResetEntry() {}
 
-void DeviceResetEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x", deviceId, policyFlags);
+std::string DeviceResetEntry::getDescription() const {
+    return StringPrintf("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x", deviceId, policyFlags);
 }
 
 // --- FocusEntry ---
@@ -126,8 +120,8 @@
 
 FocusEntry::~FocusEntry() {}
 
-void FocusEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("FocusEvent(hasFocus=%s)", hasFocus ? "true" : "false");
+std::string FocusEntry::getDescription() const {
+    return StringPrintf("FocusEvent(hasFocus=%s)", hasFocus ? "true" : "false");
 }
 
 // --- KeyEntry ---
@@ -153,12 +147,11 @@
 
 KeyEntry::~KeyEntry() {}
 
-void KeyEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("KeyEvent");
+std::string KeyEntry::getDescription() const {
     if (!GetBoolProperty("ro.debuggable", false)) {
-        return;
+        return "KeyEvent";
     }
-    msg += StringPrintf("(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, "
+    return StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, "
                         "flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, "
                         "repeatCount=%d), policyFlags=0x%08x",
                         deviceId, source, displayId, KeyEvent::actionToString(action), flags,
@@ -212,12 +205,12 @@
 
 MotionEntry::~MotionEntry() {}
 
-void MotionEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("MotionEvent");
+std::string MotionEntry::getDescription() const {
     if (!GetBoolProperty("ro.debuggable", false)) {
-        return;
+        return "MotionEvent";
     }
-    msg += StringPrintf("(deviceId=%d, source=0x%08x, displayId=%" PRId32
+    std::string msg;
+    msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32
                         ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, "
                         "buttonState=0x%08x, "
                         "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, "
@@ -235,6 +228,7 @@
                             pointerCoords[i].getY());
     }
     msg += StringPrintf("]), policyFlags=0x%08x", policyFlags);
+    return msg;
 }
 
 // --- DispatchEntry ---
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index d5b589e..ace57f1 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -81,9 +81,7 @@
 
     void release();
 
-    virtual void appendDescription(std::string& msg) const = 0;
-
-    std::string getDescription() const;
+    virtual std::string getDescription() const = 0;
 
 protected:
     EventEntry(int32_t id, Type type, nsecs_t eventTime, uint32_t policyFlags);
@@ -93,7 +91,7 @@
 
 struct ConfigurationChangedEntry : EventEntry {
     explicit ConfigurationChangedEntry(int32_t id, nsecs_t eventTime);
-    virtual void appendDescription(std::string& msg) const;
+    std::string getDescription() const override;
 
 protected:
     virtual ~ConfigurationChangedEntry();
@@ -103,7 +101,7 @@
     int32_t deviceId;
 
     DeviceResetEntry(int32_t id, nsecs_t eventTime, int32_t deviceId);
-    virtual void appendDescription(std::string& msg) const;
+    std::string getDescription() const override;
 
 protected:
     virtual ~DeviceResetEntry();
@@ -116,7 +114,7 @@
 
     FocusEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus,
                std::string_view reason);
-    virtual void appendDescription(std::string& msg) const;
+    std::string getDescription() const override;
 
 protected:
     virtual ~FocusEntry();
@@ -148,7 +146,7 @@
     KeyEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
              uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
              int32_t metaState, int32_t repeatCount, nsecs_t downTime);
-    virtual void appendDescription(std::string& msg) const;
+    std::string getDescription() const override;
     void recycle();
 
 protected:
@@ -182,7 +180,7 @@
                 float yCursorPosition, nsecs_t downTime, uint32_t pointerCount,
                 const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
                 float xOffset, float yOffset);
-    virtual void appendDescription(std::string& msg) const;
+    std::string getDescription() const override;
 
 protected:
     virtual ~MotionEntry();
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 8b4ae03..22e658a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -217,6 +217,36 @@
     }
 }
 
+static std::string dumpQueue(const std::deque<DispatchEntry*>& queue, nsecs_t currentTime) {
+    constexpr size_t maxEntries = 50; // max events to print
+    constexpr size_t skipBegin = maxEntries / 2;
+    const size_t skipEnd = queue.size() - maxEntries / 2;
+    // skip from maxEntries / 2 ... size() - maxEntries/2
+    // only print from 0 .. skipBegin and then from skipEnd .. size()
+
+    std::string dump;
+    for (size_t i = 0; i < queue.size(); i++) {
+        const DispatchEntry& entry = *queue[i];
+        if (i >= skipBegin && i < skipEnd) {
+            dump += StringPrintf(INDENT4 "<skipped %zu entries>\n", skipEnd - skipBegin);
+            i = skipEnd - 1; // it will be incremented to "skipEnd" by 'continue'
+            continue;
+        }
+        dump.append(INDENT4);
+        dump += entry.eventEntry->getDescription();
+        dump += StringPrintf(", seq=%" PRIu32
+                             ", targetFlags=0x%08x, resolvedAction=%d, age=%" PRId64 "ms",
+                             entry.seq, entry.targetFlags, entry.resolvedAction,
+                             ns2ms(currentTime - entry.eventEntry->eventTime));
+        if (entry.deliveryTime != 0) {
+            // This entry was delivered, so add information on how long we've been waiting
+            dump += StringPrintf(", wait=%" PRId64 "ms", ns2ms(currentTime - entry.deliveryTime));
+        }
+        dump.append("\n");
+    }
+    return dump;
+}
+
 /**
  * Find the entry in std::unordered_map by key, and return it.
  * If the entry is not found, return a default constructed entry.
@@ -4454,7 +4484,7 @@
         dump += StringPrintf(INDENT "RecentQueue: length=%zu\n", mRecentQueue.size());
         for (EventEntry* entry : mRecentQueue) {
             dump += INDENT2;
-            entry->appendDescription(dump);
+            dump += entry->getDescription();
             dump += StringPrintf(", age=%" PRId64 "ms\n", ns2ms(currentTime - entry->eventTime));
         }
     } else {
@@ -4465,7 +4495,7 @@
     if (mPendingEvent) {
         dump += INDENT "PendingEvent:\n";
         dump += INDENT2;
-        mPendingEvent->appendDescription(dump);
+        dump += mPendingEvent->getDescription();
         dump += StringPrintf(", age=%" PRId64 "ms\n",
                              ns2ms(currentTime - mPendingEvent->eventTime));
     } else {
@@ -4477,7 +4507,7 @@
         dump += StringPrintf(INDENT "InboundQueue: length=%zu\n", mInboundQueue.size());
         for (EventEntry* entry : mInboundQueue) {
             dump += INDENT2;
-            entry->appendDescription(dump);
+            dump += entry->getDescription();
             dump += StringPrintf(", age=%" PRId64 "ms\n", ns2ms(currentTime - entry->eventTime));
         }
     } else {
@@ -4509,14 +4539,8 @@
             if (!connection->outboundQueue.empty()) {
                 dump += StringPrintf(INDENT3 "OutboundQueue: length=%zu\n",
                                      connection->outboundQueue.size());
-                for (DispatchEntry* entry : connection->outboundQueue) {
-                    dump.append(INDENT4);
-                    entry->eventEntry->appendDescription(dump);
-                    dump += StringPrintf(", targetFlags=0x%08x, resolvedAction=%d, age=%" PRId64
-                                         "ms\n",
-                                         entry->targetFlags, entry->resolvedAction,
-                                         ns2ms(currentTime - entry->eventEntry->eventTime));
-                }
+                dump += dumpQueue(connection->outboundQueue, currentTime);
+
             } else {
                 dump += INDENT3 "OutboundQueue: <empty>\n";
             }
@@ -4524,15 +4548,7 @@
             if (!connection->waitQueue.empty()) {
                 dump += StringPrintf(INDENT3 "WaitQueue: length=%zu\n",
                                      connection->waitQueue.size());
-                for (DispatchEntry* entry : connection->waitQueue) {
-                    dump += INDENT4;
-                    entry->eventEntry->appendDescription(dump);
-                    dump += StringPrintf(", targetFlags=0x%08x, resolvedAction=%d, "
-                                         "age=%" PRId64 "ms, wait=%" PRId64 "ms seq=%" PRIu32 "\n",
-                                         entry->targetFlags, entry->resolvedAction,
-                                         ns2ms(currentTime - entry->eventEntry->eventTime),
-                                         ns2ms(currentTime - entry->deliveryTime), entry->seq);
-                }
+                dump += dumpQueue(connection->waitQueue, currentTime);
             } else {
                 dump += INDENT3 "WaitQueue: <empty>\n";
             }