Refactor ActiveGestureLog and CompoundString in preparation for ProtoLog 2.0

We will need to send formatted strings to the ProtoLog api, so it is simpler to use CompoundString as the default string storage in ActiveGestureLog.

Refactored CompoundString to be able to be broken down into a formattable string.

Flag: N/A
Fixes: 313640579
Test: ran launcher, completed gestures, dumped gesture logs
Change-Id: I5f290d1860c6bac5047cbf361537829fbe986685
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 8313e09..258f465 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1223,12 +1223,12 @@
                         : null;
         ActiveGestureLog.INSTANCE.addLog(
                 new ActiveGestureLog.CompoundString("calculateEndTarget: velocities=(x=")
-                        .append(Float.toString(dpiFromPx(velocityPxPerMs.x)))
+                        .append(dpiFromPx(velocityPxPerMs.x))
                         .append("dp/ms, y=")
-                        .append(Float.toString(dpiFromPx(velocityPxPerMs.y)))
+                        .append(dpiFromPx(velocityPxPerMs.y))
                         .append("dp/ms), angle=")
-                        .append(Double.toString(Math.toDegrees(Math.atan2(
-                                -velocityPxPerMs.y, velocityPxPerMs.x)))), gestureEvent);
+                        .append(Math.toDegrees(Math.atan2(
+                                -velocityPxPerMs.y, velocityPxPerMs.x))), gestureEvent);
 
         if (mGestureState.isHandlingAtomicEvent()) {
             // Button mode, this is only used to go to recents.
diff --git a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
index 6f4b6cb..278ca56 100644
--- a/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
+++ b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
@@ -18,6 +18,8 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.launcher3.util.Preconditions;
+
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -43,14 +45,6 @@
      */
     public static final String INTENT_EXTRA_LOG_TRACE_ID = "INTENT_EXTRA_LOG_TRACE_ID";
 
-    private static final int TYPE_ONE_OFF = 0;
-    private static final int TYPE_FLOAT = 1;
-    private static final int TYPE_INTEGER = 2;
-    private static final int TYPE_BOOL_TRUE = 3;
-    private static final int TYPE_BOOL_FALSE = 4;
-    private static final int TYPE_COMPOUND_STRING = 5;
-    private static final int TYPE_GESTURE_EVENT = 6;
-
     private final EventLog[] logs;
     private int nextIndex;
     private int mCurrentLogId = 100;
@@ -67,9 +61,12 @@
      *                   execution.
      */
     public void trackEvent(@Nullable ActiveGestureErrorDetector.GestureEvent gestureEvent) {
-        addLog(TYPE_GESTURE_EVENT, "", 0, CompoundString.NO_OP, gestureEvent);
+        addLog(CompoundString.NO_OP, gestureEvent);
     }
 
+    /**
+     * Adds a log to be printed at log-dump-time.
+     */
     public void addLog(String event) {
         addLog(event, null);
     }
@@ -82,54 +79,35 @@
         addLog(event, extras, null);
     }
 
-    public void addLog(CompoundString compoundString) {
-        if (compoundString == CompoundString.NO_OP) return;
-        addLog(TYPE_COMPOUND_STRING, "", 0, compoundString, null);
-    }
-
-    public void addLog(
-            CompoundString compoundString,
-            @Nullable ActiveGestureErrorDetector.GestureEvent gestureEvent) {
-        if (compoundString == CompoundString.NO_OP) {
-            trackEvent(gestureEvent);
-            return;
-        }
-        addLog(TYPE_COMPOUND_STRING, "", 0, compoundString, gestureEvent);
-    }
-
     /**
-     * Adds a log and track the associated event for error detection.
+     * Adds a log to be printed at log-dump-time and track the associated event for error detection.
      *
      * @param gestureEvent GestureEvent representing the event being logged.
      */
     public void addLog(
             String event, @Nullable ActiveGestureErrorDetector.GestureEvent gestureEvent) {
-        addLog(TYPE_ONE_OFF, event, 0, CompoundString.NO_OP, gestureEvent);
+        addLog(new CompoundString(event), gestureEvent);
     }
 
     public void addLog(
             String event,
             int extras,
             @Nullable ActiveGestureErrorDetector.GestureEvent gestureEvent) {
-        addLog(TYPE_INTEGER, event, extras, CompoundString.NO_OP, gestureEvent);
+        addLog(new CompoundString(event).append(": ").append(extras), gestureEvent);
     }
 
     public void addLog(
             String event,
             boolean extras,
             @Nullable ActiveGestureErrorDetector.GestureEvent gestureEvent) {
-        addLog(
-                extras ? TYPE_BOOL_TRUE : TYPE_BOOL_FALSE,
-                event,
-                0,
-                CompoundString.NO_OP,
-                gestureEvent);
+        addLog(new CompoundString(event).append(": ").append(extras), gestureEvent);
     }
 
-    private void addLog(
-            int type,
-            String event,
-            float extras,
+    public void addLog(CompoundString compoundString) {
+        addLog(compoundString, null);
+    }
+
+    public void addLog(
             CompoundString compoundString,
             @Nullable ActiveGestureErrorDetector.GestureEvent gestureEvent) {
         EventLog lastEventLog = logs[(nextIndex + logs.length - 1) % logs.length];
@@ -137,7 +115,7 @@
             EventLog eventLog = new EventLog(mCurrentLogId, mIsFullyGesturalNavMode);
             EventEntry eventEntry = new EventEntry();
 
-            eventEntry.update(type, event, extras, compoundString, gestureEvent);
+            eventEntry.update(compoundString, gestureEvent);
             eventLog.eventEntries.add(eventEntry);
             logs[nextIndex] = eventLog;
             nextIndex = (nextIndex + 1) % logs.length;
@@ -146,17 +124,17 @@
 
         // Update the last EventLog
         List<EventEntry> lastEventEntries = lastEventLog.eventEntries;
-        EventEntry lastEntry = lastEventEntries.size() > 0
+        EventEntry lastEntry = !lastEventEntries.isEmpty()
                 ? lastEventEntries.get(lastEventEntries.size() - 1) : null;
 
         // Update the last EventEntry if it's a duplicate
-        if (isEntrySame(lastEntry, type, event, extras, compoundString, gestureEvent)) {
+        if (isEntrySame(lastEntry, compoundString, gestureEvent)) {
             lastEntry.duplicateCount++;
             return;
         }
         EventEntry eventEntry = new EventEntry();
 
-        eventEntry.update(type, event, extras, compoundString, gestureEvent);
+        eventEntry.update(compoundString, gestureEvent);
         lastEventEntries.add(eventEntry);
     }
 
@@ -181,30 +159,14 @@
 
             writer.println(prefix + "\tLogs for logId: " + eventLog.logId);
             for (EventEntry eventEntry : eventLog.eventEntries) {
+                if (eventEntry.mCompoundString.mIsNoOp) {
+                    continue;
+                }
                 date.setTime(eventEntry.time);
 
-                StringBuilder msg = new StringBuilder(prefix + "\t\t").append(sdf.format(date))
-                        .append(eventEntry.event);
-                switch (eventEntry.type) {
-                    case TYPE_BOOL_FALSE:
-                        msg.append(": false");
-                        break;
-                    case TYPE_BOOL_TRUE:
-                        msg.append(": true");
-                        break;
-                    case TYPE_FLOAT:
-                        msg.append(": ").append(eventEntry.extras);
-                        break;
-                    case TYPE_INTEGER:
-                        msg.append(": ").append((int) eventEntry.extras);
-                        break;
-                    case TYPE_COMPOUND_STRING:
-                        msg.append(eventEntry.mCompoundString);
-                        break;
-                    case TYPE_GESTURE_EVENT:
-                        continue;
-                    default: // fall out
-                }
+                StringBuilder msg = new StringBuilder(prefix + "\t\t")
+                        .append(sdf.format(date))
+                        .append(eventEntry.mCompoundString);
                 if (eventEntry.duplicateCount > 0) {
                     msg.append(" & ").append(eventEntry.duplicateCount).append(" similar events");
                 }
@@ -232,15 +194,9 @@
 
     private boolean isEntrySame(
             EventEntry entry,
-            int type,
-            String event,
-            float extras,
             CompoundString compoundString,
             ActiveGestureErrorDetector.GestureEvent gestureEvent) {
         return entry != null
-                && entry.type == type
-                && entry.event.equals(event)
-                && Float.compare(entry.extras, extras) == 0
                 && entry.mCompoundString.equals(compoundString)
                 && entry.gestureEvent == gestureEvent;
     }
@@ -248,9 +204,6 @@
     /** A single event entry. */
     protected static class EventEntry {
 
-        private int type;
-        private String event;
-        private float extras;
         @NonNull private CompoundString mCompoundString;
         private ActiveGestureErrorDetector.GestureEvent gestureEvent;
         private long time;
@@ -264,14 +217,8 @@
         }
 
         private void update(
-                int type,
-                String event,
-                float extras,
                 @NonNull CompoundString compoundString,
                 ActiveGestureErrorDetector.GestureEvent gestureEvent) {
-            this.type = type;
-            this.event = event;
-            this.extras = extras;
             this.mCompoundString = compoundString;
             this.gestureEvent = gestureEvent;
             time = System.currentTimeMillis();
@@ -302,6 +249,7 @@
         public static final CompoundString NO_OP = new CompoundString();
 
         private final List<String> mSubstrings;
+        private final List<Object> mArgs;
 
         private final boolean mIsNoOp;
 
@@ -313,10 +261,12 @@
             mIsNoOp = substring == null;
             if (mIsNoOp) {
                 mSubstrings = null;
+                mArgs = null;
                 return;
             }
             mSubstrings = new ArrayList<>();
             mSubstrings.add(substring);
+            mArgs = new ArrayList<>();
         }
 
         public CompoundString append(CompoundString substring) {
@@ -338,19 +288,41 @@
         }
 
         public CompoundString append(int num) {
-            if (mIsNoOp) {
-                return this;
-            }
-            mSubstrings.add(Integer.toString(num));
+            mArgs.add(num);
 
-            return this;
+            return append("%d");
+        }
+
+        public CompoundString append(float num) {
+            mArgs.add(num);
+
+            return append("%.2f");
+        }
+
+        public CompoundString append(double num) {
+            mArgs.add(num);
+
+            return append("%.2f");
+        }
+
+        public CompoundString append(boolean bool) {
+            mArgs.add(bool);
+
+            return append("%b");
+        }
+
+        public Object[] getArgs() {
+            return mArgs.toArray();
         }
 
         @Override
         public String toString() {
-            if (mIsNoOp) {
-                return "ERROR: cannot use No-Op compound string";
-            }
+            return String.format(toUnformattedString(), getArgs());
+        }
+
+        public String toUnformattedString() {
+            Preconditions.assertTrue(!mIsNoOp);
+
             StringBuilder sb = new StringBuilder();
             for (String substring : mSubstrings) {
                 sb.append(substring);
diff --git a/src/com/android/launcher3/util/Preconditions.java b/src/com/android/launcher3/util/Preconditions.java
index 63d56e4..0e5ab9a 100644
--- a/src/com/android/launcher3/util/Preconditions.java
+++ b/src/com/android/launcher3/util/Preconditions.java
@@ -51,6 +51,12 @@
         }
     }
 
+    public static void assertTrue(boolean condition) {
+        if (FeatureFlags.IS_STUDIO_BUILD && !condition) {
+            throw new IllegalStateException();
+        }
+    }
+
     private static boolean isSameLooper(Looper looper) {
         return Looper.myLooper() == looper;
     }