Add ability to dump events in a timeline view.

Adding new event dump which shows the events for all call, sorted by
time of event.

Test: Manual
Bug: 38450166
Change-Id: I9fd4ce92bdf62ef48d6940f03db1f2388003e9fc
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 6107895..640c9e1 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -269,6 +269,23 @@
     }
 
     /**
+     * Dumps the events in a timeline format.
+     * @param pw The {@link IndentingPrintWriter} to write to.
+     * @hide
+     */
+    public static void dumpEventsTimeline(IndentingPrintWriter pw) {
+        // If the Events logger has not been initialized, then there have been no events logged.
+        // Don't load it now!
+        synchronized (sSingletonSync) {
+            if (sEventManager != null) {
+                getEventManager().dumpEventsTimeline(pw);
+            } else {
+                pw.println("No Historical Events Logged.");
+            }
+        }
+    }
+
+    /**
      * Enable or disable extended telecom logging.
      *
      * @param isExtendedLoggingEnabled {@code true} if extended logging should be enabled,
diff --git a/telecomm/java/android/telecom/Logging/EventManager.java b/telecomm/java/android/telecom/Logging/EventManager.java
index 2cd1b96..fddbfce 100644
--- a/telecomm/java/android/telecom/Logging/EventManager.java
+++ b/telecomm/java/android/telecom/Logging/EventManager.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.telecom.Log;
 import android.text.TextUtils;
+import android.util.Pair;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
@@ -27,6 +28,7 @@
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.IllegalFormatException;
@@ -35,6 +37,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.stream.Collectors;
 
 /**
  * A utility class that provides the ability to define Events that a subsystem deems important, and
@@ -49,6 +52,7 @@
     public static final String TAG = "Logging.Events";
     @VisibleForTesting
     public static final int DEFAULT_EVENTS_TO_CACHE = 10;  // Arbitrarily chosen.
+    private final DateFormat sDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
 
     public interface Loggable {
         /**
@@ -169,7 +173,6 @@
             }
         }
 
-        private final DateFormat sDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
         private final List<Event> mEvents = new LinkedList<>();
         private final Loggable mRecordEntry;
 
@@ -308,6 +311,41 @@
         pw.decreaseIndent();
     }
 
+    /**
+     * Dumps events in a timeline format.
+     * @param pw The {@link IndentingPrintWriter} to output the timeline to.
+     * @hide
+     */
+    public void dumpEventsTimeline(IndentingPrintWriter pw) {
+        pw.println("Historical Events (sorted by time):");
+
+        // Flatten event records out for sorting.
+        List<Pair<Loggable, Event>> events = new ArrayList<>();
+        for (EventRecord er : mEventRecords) {
+            for (Event ev : er.getEvents()) {
+                events.add(new Pair<>(er.getRecordEntry(), ev));
+            }
+        }
+
+        // Sort by event time.
+        Comparator<Pair<Loggable, Event>> byEventTime = (e1, e2) -> {
+          return Long.compare(e1.second.time, e2.second.time);
+        };
+        events.sort(byEventTime);
+
+        pw.increaseIndent();
+        for (Pair<Loggable, Event> event : events) {
+            pw.print(sDateFormat.format(new Date(event.second.time)));
+            pw.print(",");
+            pw.print(event.first.getId());
+            pw.print(",");
+            pw.print(event.second.eventId);
+            pw.print(",");
+            pw.println(event.second.data);
+        }
+        pw.decreaseIndent();
+    }
+
     public void changeEventCacheSize(int newSize) {
 
         // Resize the event queue.