TrackRecord: add a method to return callbacks since last poll

This change adds a backtrace() method which returns a list of events
that were received since the last time a user called poll() on a
ReadHead. This is particularly useful for logging observed events while
a poll was in progress that did not end up matching an event.

Test: atest EthernetManagerTest
Change-Id: If019cf9eb5e3e9268c5e6b74edbd8f49959cc71c
diff --git a/staticlibs/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt b/staticlibs/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt
index efd77d1..f24e4f1 100644
--- a/staticlibs/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt
+++ b/staticlibs/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt
@@ -213,6 +213,9 @@
         private val slock = StampedLock()
         private var readHead = 0
 
+        // A special mark used to track the start of the last poll() operation.
+        private var pollMark = 0
+
         /**
          * @return the current value of the mark.
          */
@@ -223,6 +226,7 @@
             val stamp = slock.tryWriteLock()
             if (0L == stamp) concurrentAccessDetected()
             readHead = v
+            pollMark = v
             slock.unlockWrite(stamp)
         }
 
@@ -261,6 +265,7 @@
         fun poll(timeoutMs: Long, predicate: (E) -> Boolean = { true }): E? {
             val stamp = slock.tryWriteLock()
             if (0L == stamp) concurrentAccessDetected()
+            pollMark = readHead
             try {
                 lock.withLock {
                     val index = pollForIndexReadLocked(timeoutMs, readHead, predicate)
@@ -273,6 +278,25 @@
         }
 
         /**
+         * Returns a list of events that were observed since the last time poll() was called on this
+         * ReadHead.
+         *
+         * @return list of events since poll() was called.
+         */
+        fun backtrace(): List<E> {
+            val stamp = slock.tryReadLock()
+            if (0L == stamp) concurrentAccessDetected()
+
+            try {
+                lock.withLock {
+                    return ArrayList(subList(pollMark, mark))
+                }
+            } finally {
+                slock.unlockRead(stamp)
+            }
+        }
+
+        /**
          * Returns the first element after the mark or null. This never blocks.
          *
          * This method is subject to threading restrictions. It can be used concurrently on