Stop device before restoring.

Device could be started when a restore happens. This will cause errors
due to instance number conflict.

Bug: 310266582
Test: m tradefed-all
Change-Id: Ibe30fc3dc2ed1c5bb0a99ac700f6e542b55b9d36
diff --git a/src/com/android/tradefed/device/internal/DeviceSnapshotFeature.java b/src/com/android/tradefed/device/internal/DeviceSnapshotFeature.java
index 0ae29ee..dfb3635 100644
--- a/src/com/android/tradefed/device/internal/DeviceSnapshotFeature.java
+++ b/src/com/android/tradefed/device/internal/DeviceSnapshotFeature.java
@@ -107,6 +107,7 @@
                 String snapshotId = request.getArgsMap().get(SNAPSHOT_ID);
                 boolean restoreFlag = Boolean.parseBoolean(request.getArgsMap().get(RESTORE_FLAG));
                 if (restoreFlag) {
+                    stop(responseBuilder, connection, user, offset);
                     restoreSnapshot(responseBuilder, connection, user, offset, snapshotId);
                 } else {
                     suspend(responseBuilder, connection, user, offset);
@@ -277,6 +278,41 @@
         }
     }
 
+    private void stop(
+            FeatureResponse.Builder responseBuilder,
+            AbstractConnection connection,
+            String user,
+            Integer offset)
+            throws DeviceNotAvailableException, TargetSetupError {
+        String response =
+                String.format(
+                        "Attempting stop device on %s (%s).",
+                        mTestInformation.getDevice().getSerialNumber(),
+                        mTestInformation.getDevice().getClass().getSimpleName());
+        try {
+            long startTime = System.currentTimeMillis();
+            CommandResult result = stopGce(connection, user, offset);
+            if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
+                throw new DeviceNotAvailableException(
+                        String.format(
+                                "Failed to stop device: %s. status:%s\n"
+                                        + "stdout: %s\n"
+                                        + "stderr:%s",
+                                mTestInformation.getDevice().getSerialNumber(),
+                                result.getStatus(),
+                                result.getStdout(),
+                                result.getStderr()),
+                        mTestInformation.getDevice().getSerialNumber(),
+                        DeviceErrorIdentifier.DEVICE_FAILED_TO_STOP);
+            }
+            response +=
+                    String.format(
+                            " Stop finished in %d ms.", System.currentTimeMillis() - startTime);
+        } finally {
+            responseBuilder.setResponse(response);
+        }
+    }
+
     private GceAvdInfo getAvdInfo(ITestDevice device, AbstractConnection connection) {
         if (connection instanceof AdbSshConnection) {
             return ((AdbSshConnection) connection).getAvdInfo();
@@ -295,7 +331,7 @@
         }
         CommandResult res = new CommandResult(CommandStatus.EXCEPTION);
         res.setStderr("Incorrect connection type while attempting device snapshot");
-        return new CommandResult(CommandStatus.EXCEPTION);
+        return res;
     }
 
     private CommandResult restoreSnapshotGce(
@@ -306,7 +342,7 @@
         }
         CommandResult res = new CommandResult(CommandStatus.EXCEPTION);
         res.setStderr("Incorrect connection type while attempting device restore");
-        return new CommandResult(CommandStatus.EXCEPTION);
+        return res;
     }
 
     private CommandResult suspendGce(AbstractConnection connection, String user, Integer offset)
@@ -316,7 +352,7 @@
         }
         CommandResult res = new CommandResult(CommandStatus.EXCEPTION);
         res.setStderr("Incorrect connection type while attempting device suspend");
-        return new CommandResult(CommandStatus.EXCEPTION);
+        return res;
     }
 
     private CommandResult resumeGce(AbstractConnection connection, String user, Integer offset)
@@ -326,6 +362,16 @@
         }
         CommandResult res = new CommandResult(CommandStatus.EXCEPTION);
         res.setStderr("Incorrect connection type while attempting device resume");
-        return new CommandResult(CommandStatus.EXCEPTION);
+        return res;
+    }
+
+    private CommandResult stopGce(AbstractConnection connection, String user, Integer offset)
+            throws TargetSetupError {
+        if (connection instanceof AdbSshConnection) {
+            return ((AdbSshConnection) connection).stopGce(user, offset);
+        }
+        CommandResult res = new CommandResult(CommandStatus.EXCEPTION);
+        res.setStderr("Incorrect connection type while attempting device stop");
+        return res;
     }
 }