Merge "Implement a single interface to consume events from EventLogger"
diff --git a/services/core/java/com/android/server/utils/EventLogger.java b/services/core/java/com/android/server/utils/EventLogger.java
index 11766a3..770cb72 100644
--- a/services/core/java/com/android/server/utils/EventLogger.java
+++ b/services/core/java/com/android/server/utils/EventLogger.java
@@ -26,7 +26,9 @@
 import java.lang.annotation.RetentionPolicy;
 import java.text.SimpleDateFormat;
 import java.util.ArrayDeque;
+import java.util.ArrayList;
 import java.util.Date;
+import java.util.List;
 import java.util.Locale;
 
 /**
@@ -79,20 +81,34 @@
         enqueue(event.printLog(logType, tag));
     }
 
+    /** Dumps events into the given {@link DumpSink}. */
+    public synchronized void dump(DumpSink dumpSink) {
+        dumpSink.sink(mTag, new ArrayList<>(mEvents));
+    }
+
     /** Dumps events using {@link PrintWriter}. */
     public synchronized void dump(PrintWriter pw) {
         dump(pw, "" /* prefix */);
     }
 
     /** Dumps events using {@link PrintWriter} with a certain indent. */
-    public synchronized void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + "Events log: " + mTag);
-        String indent = prefix + "  ";
+    public synchronized void dump(PrintWriter pw, String indent) {
+        pw.println(indent + "Events log: " + mTag);
+
+        String childrenIndention = indent + "  ";
         for (Event evt : mEvents) {
-            pw.println(indent + evt.toString());
+            pw.println(childrenIndention + evt.toString());
         }
     }
 
+    /** Receives events from {@link EventLogger} upon a {@link #dump(DumpSink)} call. **/
+    public interface DumpSink {
+
+        /** Processes given events into some pipeline with a given tag. **/
+        void sink(String tag, List<Event> events);
+
+    }
+
     public abstract static class Event {
 
         /** Timestamps formatter. */
diff --git a/services/tests/servicestests/src/com/android/server/utils/EventLoggerTest.java b/services/tests/servicestests/src/com/android/server/utils/EventLoggerTest.java
index 4762696..aafc16d 100644
--- a/services/tests/servicestests/src/com/android/server/utils/EventLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/EventLoggerTest.java
@@ -29,8 +29,10 @@
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 
 @SmallTest
 @RunWith(Enclosed.class)
@@ -51,17 +53,25 @@
         private StringWriter mTestStringWriter;
         private PrintWriter mTestPrintWriter;
 
+        private TestDumpSink mTestConsumer;
         private EventLogger mEventLogger;
 
         @Before
         public void setUp() {
             mTestStringWriter = new StringWriter();
             mTestPrintWriter = new PrintWriter(mTestStringWriter);
+            mTestConsumer = new TestDumpSink();
             mEventLogger = new EventLogger(EVENTS_LOGGER_SIZE, EVENTS_LOGGER_TAG);
         }
 
         @Test
-        public void testThatConsumeOfEmptyLoggerProducesEmptyList() {
+        public void testThatConsumerProducesEmptyListFromEmptyLog() {
+            mEventLogger.dump(mTestConsumer);
+            assertThat(mTestConsumer.getLastKnownConsumedEvents()).isEmpty();
+        }
+
+        @Test
+        public void testThatPrintWriterProducesEmptyListFromEmptyLog() {
             mEventLogger.dump(mTestPrintWriter);
             assertThat(mTestStringWriter.toString()).isEmpty();
         }
@@ -102,10 +112,12 @@
             });
         }
 
+        private TestDumpSink mTestConsumer;
         private EventLogger mEventLogger;
 
         private final StringWriter mTestStringWriter;
         private final PrintWriter mTestPrintWriter;
+
         private final EventLogger.Event[] mEventsToInsert;
         private final EventLogger.Event[] mExpectedEvents;
 
@@ -119,11 +131,25 @@
 
         @Before
         public void setUp() {
+            mTestConsumer = new TestDumpSink();
             mEventLogger = new EventLogger(EVENTS_LOGGER_SIZE, EVENTS_LOGGER_TAG);
         }
 
         @Test
-        public void testThatLoggingWorksAsExpected() {
+        public void testThatConsumerDumpsEventsAsExpected() {
+            for (EventLogger.Event event: mEventsToInsert) {
+                mEventLogger.enqueue(event);
+            }
+
+            mEventLogger.dump(mTestConsumer);
+
+            assertThat(mTestConsumer.getLastKnownConsumedEvents())
+                    .containsExactlyElementsIn(mExpectedEvents);
+        }
+
+
+        @Test
+        public void testThatPrintWriterDumpsEventsAsExpected() {
             for (EventLogger.Event event: mEventsToInsert) {
                 mEventLogger.enqueue(event);
             }
@@ -149,11 +175,27 @@
         return stringWriter.toString();
     }
 
-    private static class TestEvent extends EventLogger.Event {
+
+    private static final class TestEvent extends EventLogger.Event {
 
         @Override
         public String eventToString() {
             return getClass().getName() + "@" + Integer.toHexString(hashCode());
         }
     }
+
+    private static final class TestDumpSink implements EventLogger.DumpSink {
+
+        private final ArrayList<EventLogger.Event> mEvents = new ArrayList<>();
+
+        @Override
+        public void sink(String tag, List<EventLogger.Event> events) {
+            mEvents.clear();
+            mEvents.addAll(events);
+        }
+
+        public ArrayList<EventLogger.Event> getLastKnownConsumedEvents() {
+            return new ArrayList<>(mEvents);
+        }
+    }
 }