Merge "Log if invocation was interrupted due to TF stop" into oc-dev
diff --git a/src/com/android/tradefed/command/CommandScheduler.java b/src/com/android/tradefed/command/CommandScheduler.java
index 82b84e9..80f00b3 100644
--- a/src/com/android/tradefed/command/CommandScheduler.java
+++ b/src/com/android/tradefed/command/CommandScheduler.java
@@ -673,6 +673,7 @@
          * all running invocations.
          */
         public void stopInvocation(String message) {
+            getInvocation().notifyInvocationStopped();
             for (ITestDevice device : mInvocationContext.getDevices()) {
                 if (device != null && device.getIDevice().isOnline()) {
                     // Kill all running processes on device.
diff --git a/src/com/android/tradefed/invoker/ITestInvocation.java b/src/com/android/tradefed/invoker/ITestInvocation.java
index 31ae6db..d2d29c1 100644
--- a/src/com/android/tradefed/invoker/ITestInvocation.java
+++ b/src/com/android/tradefed/invoker/ITestInvocation.java
@@ -61,4 +61,7 @@
     public void invoke(IInvocationContext metadata, IConfiguration config,
             IRescheduler rescheduler, ITestInvocationListener... extraListeners)
             throws DeviceNotAvailableException, Throwable;
+
+    /** Notify the {@link TestInvocation} that TradeFed has been requested to stop. */
+    public default void notifyInvocationStopped() {}
 }
diff --git a/src/com/android/tradefed/invoker/TestInvocation.java b/src/com/android/tradefed/invoker/TestInvocation.java
index d70b025..32d1054 100644
--- a/src/com/android/tradefed/invoker/TestInvocation.java
+++ b/src/com/android/tradefed/invoker/TestInvocation.java
@@ -115,6 +115,7 @@
     }
 
     private String mStatus = "(not invoked)";
+    private boolean mStopRequested = false;
 
     /**
      * A {@link ResultForwarder} for forwarding resumed invocations.
@@ -473,6 +474,17 @@
                 for (ITestDevice device : context.getDevices()) {
                     reportLogs(device, listener, Stage.TEARDOWN);
                 }
+                if (mStopRequested) {
+                    CLog.e(
+                            "====================================================================="
+                                    + "====");
+                    CLog.e(
+                            "Invocation was interrupted due to TradeFed stop, results will be "
+                                    + "affected.");
+                    CLog.e(
+                            "====================================================================="
+                                    + "====");
+                }
                 reportHostLog(listener, config.getLogOutput());
                 elapsedTime = System.currentTimeMillis() - startTime;
                 if (!resumed) {
@@ -969,4 +981,9 @@
     public static String getEmulatorLogName(Stage stage) {
         return EMULATOR_LOG_NAME_PREFIX + stage.getName();
     }
+
+    @Override
+    public void notifyInvocationStopped() {
+        mStopRequested = true;
+    }
 }
diff --git a/tests/src/com/android/tradefed/command/CommandSchedulerFuncTest.java b/tests/src/com/android/tradefed/command/CommandSchedulerFuncTest.java
index 5fa7fdf..3fe0cb9 100644
--- a/tests/src/com/android/tradefed/command/CommandSchedulerFuncTest.java
+++ b/tests/src/com/android/tradefed/command/CommandSchedulerFuncTest.java
@@ -197,6 +197,7 @@
         Integer mFastCount = 0;
         Integer mSlowCountLimit = 40;
         public boolean runInterrupted = false;
+        public boolean printedStop = false;
 
         @Deprecated
         @Override
@@ -244,7 +245,12 @@
                         throws DeviceNotAvailableException, Throwable {
             invoke(metadata.getDevices().get(0), config, rescheduler, extraListeners);
         }
-   }
+
+        @Override
+        public void notifyInvocationStopped() {
+            printedStop = true;
+        }
+    }
 
     /**
      * Test that the Invocation is not interruptible even when Battery is low.
@@ -285,6 +291,8 @@
         mCommandScheduler.shutdown();
         mCommandScheduler.join(WAIT_TIMEOUT_MS);
         assertFalse(mMockTestInvoker.runInterrupted);
+        // Notify was not sent to the invocation because it was not forced shutdown.
+        assertFalse(mMockTestInvoker.printedStop);
     }
 
     /**
@@ -370,6 +378,8 @@
         mCommandScheduler.join(WAIT_TIMEOUT_MS);
         // Was interrupted during execution.
         assertTrue(mMockTestInvoker.runInterrupted);
+        // Notify was sent to the invocation
+        assertTrue(mMockTestInvoker.printedStop);
     }
 
     /**
@@ -445,6 +455,8 @@
         mCommandScheduler.join(WAIT_TIMEOUT_MS);
         // Stop but was not interrupted
         assertFalse(mMockTestInvoker.runInterrupted);
+        // Notify was sent to the invocation
+        assertTrue(mMockTestInvoker.printedStop);
     }
 
     private class LongInvocation implements ITestInvocation {