Split ActionStatusMessage into separate events.

ActionStatusMessage had a very strange API in the sense that it carried
multiple different statuses but these were not explicitly represented
anywhere: callers had to guess what status was represented by a combination
of the values of the fields in the message.

To fix this, split the status updates into separate events with good names
and types.  This keeps each event restricted to the data it has to carry,
preventing callers from having to guess what is or is not available, and
matches what we do for many of the other action-related events.

Note that it'd be slightly nicer to use an enum of some form so that callers
could be guaranteed to handle all possible status cases... but doing so
results in even more convoluted code because each status needs to carry
different information around.

This change highlights two more deficiencies that I am fixing.  First,
there is no such thing as a "preparing" event separate from an "started"
event so I removed the former representation.  Second, the "messages" in
the status messages were used to update the UI, thus conflating internal
status representations with the specific ways in which they should be
displayed to the users; I just pushed the formatting responsibility to
the UI modules instead.

Necessary cleanup to address https://github.com/bazelbuild/bazel/issues/7345.

RELNOTES: None.
PiperOrigin-RevId: 235051214
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporter.java b/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporter.java
index 6c2aaf3..c1a2081 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporter.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporter.java
@@ -48,6 +48,8 @@
   // Maximum number of lines to output per each status category before truncation.
   private static final int MAX_LINES = 10;
 
+  private static final String PREPARING_MESSAGE = "Preparing";
+
   private final EventHandler eventHandler;
   private final EventBus eventBus;
   private final Clock clock;
@@ -109,10 +111,27 @@
   }
 
   @Subscribe
-  public void updateStatus(ActionStatusMessage statusMsg) {
-    String message = statusMsg.getMessage();
-    ActionExecutionMetadata action = statusMsg.getActionMetadata();
-    setStatus(action, message);
+  public void updateStatus(ActionStartedEvent event) {
+    ActionExecutionMetadata action = event.getAction();
+    setStatus(action, PREPARING_MESSAGE);
+  }
+
+  @Subscribe
+  public void updateStatus(AnalyzingActionEvent event) {
+    ActionExecutionMetadata action = event.getActionMetadata();
+    setStatus(action, "Analyzing");
+  }
+
+  @Subscribe
+  public void updateStatus(SchedulingActionEvent event) {
+    ActionExecutionMetadata action = event.getActionMetadata();
+    setStatus(action, "Scheduling");
+  }
+
+  @Subscribe
+  public void updateStatus(RunningActionEvent event) {
+    ActionExecutionMetadata action = event.getActionMetadata();
+    setStatus(action, String.format("Running (%s)", event.getStrategy()));
   }
 
   public int getCount() {
@@ -204,7 +223,7 @@
     Iterator<ActionExecutionMetadata> iterator = statusMap.keySet().iterator();
     while (iterator.hasNext()) {
       // Filter out actions that are not executed yet.
-      if (statusMap.get(iterator.next()).first.equals(ActionStatusMessage.PREPARING)) {
+      if (PREPARING_MESSAGE.equals(statusMap.get(iterator.next()).first)) {
         iterator.remove();
       }
     }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionStatusMessage.java b/src/main/java/com/google/devtools/build/lib/actions/ActionStatusMessage.java
deleted file mode 100644
index 1f98df9..0000000
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionStatusMessage.java
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.lib.actions;
-
-import com.google.common.base.Preconditions;
-import com.google.devtools.build.lib.events.ExtendedEventHandler;
-
-/**
- * A message used to update in-flight action status. An action's status may change low down in the
- * execution stack (for instance, from running remotely to running locally), so this message can be
- * used to notify any interested parties.
- */
-public class ActionStatusMessage implements ExtendedEventHandler.ProgressLike {
-  private final ActionExecutionMetadata action;
-  private final String message;
-  private final String strategy;
-  public static final String PREPARING = "Preparing";
-
-  private ActionStatusMessage(ActionExecutionMetadata action, String message, String strategy) {
-    this.action = action;
-    this.message = message;
-    this.strategy = strategy;
-  }
-
-  public ActionExecutionMetadata getActionMetadata() {
-    return action;
-  }
-
-  public String getMessage() {
-    return message;
-  }
-
-  /**
-   * Return the strategy of the action; null if not created by {@link #runningStrategy}.
-   */
-  public String getStrategy() {
-    return strategy;
-  }
-
-  /** Creates "Analyzing" status message. */
-  public static ActionStatusMessage analysisStrategy(ActionExecutionMetadata action) {
-    Preconditions.checkNotNull(action.getOwner());
-    return new ActionStatusMessage(action, "Analyzing", null);
-  }
-
-  /** Creates "Preparing" status message. */
-  public static ActionStatusMessage preparingStrategy(ActionExecutionMetadata action) {
-    Preconditions.checkNotNull(action.getOwner());
-    return new ActionStatusMessage(action, PREPARING, null);
-  }
-
-  /** Creates "Scheduling" status message. */
-  public static ActionStatusMessage schedulingStrategy(ActionExecutionMetadata action) {
-    Preconditions.checkNotNull(action.getOwner());
-    return new ActionStatusMessage(action, "Scheduling", null);
-  }
-
-  /** Creates "Running (strategy)" status message. */
-  public static ActionStatusMessage runningStrategy(
-      ActionExecutionMetadata action, String strategy) {
-    Preconditions.checkNotNull(action.getOwner());
-    return new ActionStatusMessage(action, String.format("Running (%s)", strategy), strategy);
-  }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/actions/AnalyzingActionEvent.java b/src/main/java/com/google/devtools/build/lib/actions/AnalyzingActionEvent.java
new file mode 100644
index 0000000..e1609df
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/actions/AnalyzingActionEvent.java
@@ -0,0 +1,38 @@
+// Copyright 2019 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.actions;
+
+import com.google.devtools.build.lib.events.ExtendedEventHandler.ProgressLike;
+
+/**
+ * Notifies that an in-flight action has started being analyzed.
+ *
+ * <p>This event should only appear in-between corresponding {@link ActionStartedEvent} and {@link
+ * ActionCompletionEvent} events. TODO(jmmv): But this theory is not true today. Investigate.
+ */
+public class AnalyzingActionEvent implements ProgressLike {
+
+  private final ActionExecutionMetadata action;
+
+  /** Constructs a new event. */
+  public AnalyzingActionEvent(ActionExecutionMetadata action) {
+    this.action = action;
+  }
+
+  /** Gets the metadata associated with the action being analyzed. */
+  public ActionExecutionMetadata getActionMetadata() {
+    return action;
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/actions/RunningActionEvent.java b/src/main/java/com/google/devtools/build/lib/actions/RunningActionEvent.java
new file mode 100644
index 0000000..cabbbd3
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/actions/RunningActionEvent.java
@@ -0,0 +1,47 @@
+// Copyright 2019 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.actions;
+
+import com.google.devtools.build.lib.events.ExtendedEventHandler.ProgressLike;
+
+/**
+ * Notifies that an in-flight action is running.
+ *
+ * <p>This event should only appear in-between corresponding {@link ActionStartedEvent} and {@link
+ * ActionCompletionEvent} events, and should only appear after corresponding {@link
+ * AnalyzingActionEvent} and {@link SchedulingActionEvent} events. TODO(jmmv): But this theory is
+ * not true today. Investigate.
+ */
+public class RunningActionEvent implements ProgressLike {
+
+  private final ActionExecutionMetadata action;
+  private final String strategy;
+
+  /** Constructs a new event. */
+  public RunningActionEvent(ActionExecutionMetadata action, String strategy) {
+    this.action = action;
+    this.strategy = strategy;
+  }
+
+  /** Gets the metadata associated with the action that is running. */
+  public ActionExecutionMetadata getActionMetadata() {
+    return action;
+  }
+
+  /** Gets the name of the strategy used to run the action. */
+  public String getStrategy() {
+    return strategy;
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/actions/SchedulingActionEvent.java b/src/main/java/com/google/devtools/build/lib/actions/SchedulingActionEvent.java
new file mode 100644
index 0000000..ea1fa66
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/actions/SchedulingActionEvent.java
@@ -0,0 +1,39 @@
+// Copyright 2019 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.actions;
+
+import com.google.devtools.build.lib.events.ExtendedEventHandler.ProgressLike;
+
+/**
+ * Notifies that an in-flight action is being scheduled.
+ *
+ * <p>This event should only appear in-between corresponding {@link ActionStartedEvent} and {@link
+ * ActionCompletionEvent} events, and should only appear after a corresponding {@link
+ * AnalyzingActionEvent}. TODO(jmmv): But this theory is not true today. Investigate.
+ */
+public class SchedulingActionEvent implements ProgressLike {
+
+  private final ActionExecutionMetadata action;
+
+  /** Constructs a new event. */
+  public SchedulingActionEvent(ActionExecutionMetadata action) {
+    this.action = action;
+  }
+
+  /** Gets the metadata associated with the action being scheduled. */
+  public ActionExecutionMetadata getActionMetadata() {
+    return action;
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/exec/AbstractSpawnStrategy.java b/src/main/java/com/google/devtools/build/lib/exec/AbstractSpawnStrategy.java
index 9759999..189bb9e 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/AbstractSpawnStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/AbstractSpawnStrategy.java
@@ -20,13 +20,14 @@
 import com.google.devtools.build.lib.actions.ActionExecutionContext;
 import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
 import com.google.devtools.build.lib.actions.ActionInput;
-import com.google.devtools.build.lib.actions.ActionStatusMessage;
 import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
 import com.google.devtools.build.lib.actions.ArtifactPathResolver;
 import com.google.devtools.build.lib.actions.EnvironmentalExecException;
 import com.google.devtools.build.lib.actions.ExecException;
 import com.google.devtools.build.lib.actions.MetadataProvider;
+import com.google.devtools.build.lib.actions.RunningActionEvent;
 import com.google.devtools.build.lib.actions.SandboxedSpawnActionContext;
+import com.google.devtools.build.lib.actions.SchedulingActionEvent;
 import com.google.devtools.build.lib.actions.Spawn;
 import com.google.devtools.build.lib.actions.SpawnActionContext;
 import com.google.devtools.build.lib.actions.SpawnResult;
@@ -267,10 +268,10 @@
       switch (state) {
         case EXECUTING:
         case CHECKING_CACHE:
-          eventHandler.post(ActionStatusMessage.runningStrategy(action, name));
+          eventHandler.post(new RunningActionEvent(action, name));
           break;
         case SCHEDULING:
-          eventHandler.post(ActionStatusMessage.schedulingStrategy(action));
+          eventHandler.post(new SchedulingActionEvent(action));
           break;
         default:
           break;
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
index d4c36c1..6a27cbb 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
@@ -21,7 +21,9 @@
 import com.google.common.util.concurrent.Uninterruptibles;
 import com.google.devtools.build.lib.actions.ActionCompletionEvent;
 import com.google.devtools.build.lib.actions.ActionStartedEvent;
-import com.google.devtools.build.lib.actions.ActionStatusMessage;
+import com.google.devtools.build.lib.actions.AnalyzingActionEvent;
+import com.google.devtools.build.lib.actions.RunningActionEvent;
+import com.google.devtools.build.lib.actions.SchedulingActionEvent;
 import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent;
 import com.google.devtools.build.lib.analysis.NoBuildEvent;
 import com.google.devtools.build.lib.analysis.NoBuildRequestFinishedEvent;
@@ -761,8 +763,22 @@
 
   @Subscribe
   @AllowConcurrentEvents
-  public void actionStatusMessage(ActionStatusMessage event) {
-    stateTracker.actionStatusMessage(event);
+  public void analyzingAction(AnalyzingActionEvent event) {
+    stateTracker.analyzingAction(event);
+    refresh();
+  }
+
+  @Subscribe
+  @AllowConcurrentEvents
+  public void schedulingAction(SchedulingActionEvent event) {
+    stateTracker.schedulingAction(event);
+    refresh();
+  }
+
+  @Subscribe
+  @AllowConcurrentEvents
+  public void runningAction(RunningActionEvent event) {
+    stateTracker.runningAction(event);
     refresh();
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java
index 324edfb..512eb69 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalStateTracker.java
@@ -20,7 +20,9 @@
 import com.google.devtools.build.lib.actions.Action;
 import com.google.devtools.build.lib.actions.ActionCompletionEvent;
 import com.google.devtools.build.lib.actions.ActionStartedEvent;
-import com.google.devtools.build.lib.actions.ActionStatusMessage;
+import com.google.devtools.build.lib.actions.AnalyzingActionEvent;
+import com.google.devtools.build.lib.actions.RunningActionEvent;
+import com.google.devtools.build.lib.actions.SchedulingActionEvent;
 import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.bugreport.BugReport;
@@ -280,27 +282,37 @@
     }
   }
 
-  void actionStatusMessage(ActionStatusMessage event) {
+  void analyzingAction(AnalyzingActionEvent event) {
+    String name = event.getActionMetadata().getPrimaryOutput().getPath().getPathString();
+    ActionState state = activeActions.remove(name);
+    if (state != null) {
+      activeActions.put(
+          name, new ActionState(state.action, clock.nanoTime(), /*executing=*/ false, "Analyzing"));
+    }
+    notStartedActionStatus.remove(name);
+  }
+
+  void schedulingAction(SchedulingActionEvent event) {
+    String name = event.getActionMetadata().getPrimaryOutput().getPath().getPathString();
+    ActionState state = activeActions.remove(name);
+    if (state != null) {
+      activeActions.put(
+          name,
+          new ActionState(state.action, clock.nanoTime(), /*executing=*/ false, "Scheduling"));
+    }
+    notStartedActionStatus.remove(name);
+  }
+
+  void runningAction(RunningActionEvent event) {
     String strategy = event.getStrategy();
     String name = event.getActionMetadata().getPrimaryOutput().getPath().getPathString();
 
     ActionState state = activeActions.remove(name);
-
-    if (strategy != null) {
-      if (state != null) {
-        activeActions.put(
-            name, new ActionState(state.action, clock.nanoTime(), /*executing=*/ true, strategy));
-      } else {
-        notStartedActionStatus.put(name, strategy);
-      }
+    if (state != null) {
+      activeActions.put(
+          name, new ActionState(state.action, clock.nanoTime(), /*executing=*/ true, strategy));
     } else {
-      if (state != null) {
-        activeActions.put(
-            name,
-            new ActionState(
-                state.action, clock.nanoTime(), /*executing=*/ false, event.getMessage()));
-      }
-      notStartedActionStatus.remove(name);
+      notStartedActionStatus.put(name, strategy);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
index 08a1cc8..a497c6b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeActionExecutor.java
@@ -44,9 +44,9 @@
 import com.google.devtools.build.lib.actions.ActionResult;
 import com.google.devtools.build.lib.actions.ActionResultReceivedEvent;
 import com.google.devtools.build.lib.actions.ActionStartedEvent;
-import com.google.devtools.build.lib.actions.ActionStatusMessage;
 import com.google.devtools.build.lib.actions.Actions;
 import com.google.devtools.build.lib.actions.AlreadyReportedActionExecutionException;
+import com.google.devtools.build.lib.actions.AnalyzingActionEvent;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.Artifact.ArtifactExpanderImpl;
 import com.google.devtools.build.lib.actions.Artifact.OwnerlessArtifactWrapper;
@@ -715,7 +715,7 @@
       // streams is sufficient.
       setupActionFsFileOutErr(actionExecutionContext.getFileOutErr(), action);
     }
-    actionExecutionContext.getEventHandler().post(ActionStatusMessage.analysisStrategy(action));
+    actionExecutionContext.getEventHandler().post(new AnalyzingActionEvent(action));
     try {
       return action.discoverInputs(actionExecutionContext);
     } catch (ActionExecutionException e) {
@@ -846,8 +846,9 @@
           // TODO(ulfjack): Change the uses of ActionStartedEvent and ActionCompletionEvent such
           // that they can be reposted when rewinding and simplify this code path. Maybe also keep
           // track of the rewind attempt, so that listeners can use that to adjust their behavior.
-          statusReporter.updateStatus(ActionStatusMessage.preparingStrategy(action));
-          env.getListener().post(new ActionStartedEvent(action, actionStartTime));
+          ActionStartedEvent event = new ActionStartedEvent(action, actionStartTime);
+          statusReporter.updateStatus(event);
+          env.getListener().post(event);
           Preconditions.checkState(
               actionExecutionContext.getMetadataHandler() == metadataHandler,
               "%s %s",
diff --git a/src/test/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporterTest.java b/src/test/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporterTest.java
index 3aedd9d..264f0e6 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporterTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/ActionExecutionStatusReporterTest.java
@@ -157,7 +157,7 @@
     verifyOutput("Still waiting for 1 job to complete:", "Running (remote):", "action1, 1 s");
     clock.advanceMillis(1000);
 
-    eventBus.post(ActionStatusMessage.analysisStrategy(action));
+    eventBus.post(new AnalyzingActionEvent(action));
     // Locality strategy was changed, so timer was reset to 0 s.
     verifyOutput("Still waiting for 1 job to complete:", "Analyzing:", "action1, 0 s");
     statusReporter.remove(action);
@@ -262,14 +262,14 @@
   }
 
   private void setScheduling(ActionExecutionMetadata action) {
-    eventBus.post(ActionStatusMessage.schedulingStrategy(action));
+    eventBus.post(new SchedulingActionEvent(action));
   }
 
-  private void setPreparing(ActionExecutionMetadata action) {
-    eventBus.post(ActionStatusMessage.preparingStrategy(action));
+  private void setPreparing(Action action) {
+    eventBus.post(new ActionStartedEvent(action, 0));
   }
 
   private void setRunning(ActionExecutionMetadata action, String strategy) {
-    eventBus.post(ActionStatusMessage.runningStrategy(action, strategy));
+    eventBus.post(new RunningActionEvent(action, strategy));
   }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/runtime/ExperimentalStateTrackerTest.java b/src/test/java/com/google/devtools/build/lib/runtime/ExperimentalStateTrackerTest.java
index dd7d6e6..8176c32 100644
--- a/src/test/java/com/google/devtools/build/lib/runtime/ExperimentalStateTrackerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/runtime/ExperimentalStateTrackerTest.java
@@ -30,9 +30,11 @@
 import com.google.devtools.build.lib.actions.ActionLookupData;
 import com.google.devtools.build.lib.actions.ActionOwner;
 import com.google.devtools.build.lib.actions.ActionStartedEvent;
-import com.google.devtools.build.lib.actions.ActionStatusMessage;
+import com.google.devtools.build.lib.actions.AnalyzingActionEvent;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.ArtifactRoot;
+import com.google.devtools.build.lib.actions.RunningActionEvent;
+import com.google.devtools.build.lib.actions.SchedulingActionEvent;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
 import com.google.devtools.build.lib.bazel.repository.downloader.DownloadProgressEvent;
 import com.google.devtools.build.lib.buildeventstream.AnnounceBuildEventTransportsEvent;
@@ -485,7 +487,7 @@
     ExperimentalStateTracker stateTracker = new ExperimentalStateTracker(clock);
     stateTracker.actionStarted(
         new ActionStartedEvent(mockAction("Some random action", primaryOutput), clock.nanoTime()));
-    stateTracker.actionStatusMessage(ActionStatusMessage.runningStrategy(actionMetadata, strategy));
+    stateTracker.runningAction(new RunningActionEvent(actionMetadata, strategy));
 
     LoggingTerminalWriter terminalWriter = new LoggingTerminalWriter(/*discardHighlight=*/ true);
     stateTracker.writeProgressBar(terminalWriter);
@@ -589,7 +591,7 @@
 
     // Action foo being analyzed.
     stateTracker.actionStarted(new ActionStartedEvent(actionFoo, 123456700));
-    stateTracker.actionStatusMessage(ActionStatusMessage.analysisStrategy(actionFoo));
+    stateTracker.analyzingAction(new AnalyzingActionEvent(actionFoo));
 
     terminalWriter = new LoggingTerminalWriter(/*discardHighlight=*/ true);
     stateTracker.writeProgressBar(terminalWriter);
@@ -600,7 +602,7 @@
 
     // Then action bar gets scheduled.
     stateTracker.actionStarted(new ActionStartedEvent(actionBar, 123456701));
-    stateTracker.actionStatusMessage(ActionStatusMessage.schedulingStrategy(actionBar));
+    stateTracker.schedulingAction(new SchedulingActionEvent(actionBar));
 
     terminalWriter = new LoggingTerminalWriter(/*discardHighlight=*/ true);
     stateTracker.writeProgressBar(terminalWriter);
@@ -619,7 +621,7 @@
         .isTrue();
 
     // Then foo starts.
-    stateTracker.actionStatusMessage(ActionStatusMessage.runningStrategy(actionFoo, "xyz-sandbox"));
+    stateTracker.runningAction(new RunningActionEvent(actionFoo, "xyz-sandbox"));
     stateTracker.writeProgressBar(terminalWriter);
 
     terminalWriter = new LoggingTerminalWriter(/*discardHighlight=*/ true);
@@ -662,10 +664,10 @@
     when(actionBar.getOwner()).thenReturn(ownerBar);
 
     stateTracker.actionStarted(new ActionStartedEvent(actionFoo, clock.nanoTime()));
-    stateTracker.actionStatusMessage(ActionStatusMessage.runningStrategy(actionFoo, "foo-sandbox"));
+    stateTracker.runningAction(new RunningActionEvent(actionFoo, "foo-sandbox"));
     clock.advanceMillis(TimeUnit.SECONDS.toMillis(7));
     stateTracker.actionStarted(new ActionStartedEvent(actionBar, clock.nanoTime()));
-    stateTracker.actionStatusMessage(ActionStatusMessage.schedulingStrategy(actionBar));
+    stateTracker.schedulingAction(new SchedulingActionEvent(actionBar));
     clock.advanceMillis(TimeUnit.SECONDS.toMillis(21));
 
     terminalWriter = new LoggingTerminalWriter(/*discardHighlight=*/ true);
@@ -678,7 +680,7 @@
         .that(output.contains("21s"))
         .isTrue();
 
-    stateTracker.actionStatusMessage(ActionStatusMessage.runningStrategy(actionBar, "bar-sandbox"));
+    stateTracker.runningAction(new RunningActionEvent(actionBar, "bar-sandbox"));
     terminalWriter = new LoggingTerminalWriter(/*discardHighlight=*/ true);
     stateTracker.writeProgressBar(terminalWriter);
     output = terminalWriter.getTranscript();
@@ -714,7 +716,7 @@
     String output;
 
     // Early status announcement
-    stateTracker.actionStatusMessage(ActionStatusMessage.runningStrategy(actionFoo, "foo-sandbox"));
+    stateTracker.runningAction(new RunningActionEvent(actionFoo, "foo-sandbox"));
 
     // Here we don't expect any particular output, just some description; in particular, we do
     // not expect the state tracker to hit an internal error.
@@ -746,7 +748,7 @@
       ActionOwner owner = Mockito.mock(ActionOwner.class);
       when(action.getOwner()).thenReturn(owner);
       stateTracker.actionStarted(new ActionStartedEvent(action, 123456789 + i));
-      stateTracker.actionStatusMessage(ActionStatusMessage.schedulingStrategy(action));
+      stateTracker.schedulingAction(new SchedulingActionEvent(action));
     }
 
     for (int i = 0; i < 3; i++) {
@@ -754,7 +756,7 @@
       ActionOwner owner = Mockito.mock(ActionOwner.class);
       when(action.getOwner()).thenReturn(owner);
       stateTracker.actionStarted(new ActionStartedEvent(action, 123457000 + i));
-      stateTracker.actionStatusMessage(ActionStatusMessage.runningStrategy(action, "xyz-sandbox"));
+      stateTracker.runningAction(new RunningActionEvent(action, "xyz-sandbox"));
 
       LoggingTerminalWriter terminalWriter = new LoggingTerminalWriter(/*discardHighlight=*/ true);
       stateTracker.writeProgressBar(terminalWriter);