Move runShellCommandWithTimeout from UserLifecycleTests to ShellHelper

Bug: 274491131
Test: atest UserLifecycleTests
Change-Id: I9cfa39f119be60dae98cfab12bfe3f261dec83c0
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 9ba94c8..91f0681 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -70,7 +70,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Perf tests for user life cycle events.
@@ -1472,7 +1471,8 @@
     private void removeUser(int userId) throws RemoteException {
         stopUserAfterWaitingForBroadcastIdle(userId, true);
         try {
-            runShellCommandWithTimeout("pm remove-user -w " + userId, TIMEOUT_IN_SECOND);
+            ShellHelper.runShellCommandWithTimeout("pm remove-user -w " + userId,
+                    TIMEOUT_IN_SECOND);
         } catch (TimeoutException e) {
             Log.e(TAG, String.format("Could not remove user %d in %d seconds",
                     userId, TIMEOUT_IN_SECOND), e);
@@ -1539,7 +1539,7 @@
 
     private void waitForBroadcastIdle() {
         try {
-            runShellCommandWithTimeout("am wait-for-broadcast-idle", TIMEOUT_IN_SECOND);
+            ShellHelper.runShellCommandWithTimeout("am wait-for-broadcast-idle", TIMEOUT_IN_SECOND);
         } catch (TimeoutException e) {
             Log.e(TAG, "Ending waitForBroadcastIdle because it is taking too long", e);
         }
@@ -1558,41 +1558,4 @@
         waitForBroadcastIdle();
         sleep(tenSeconds);
     }
-
-    /**
-     * Runs a Shell command with a timeout, returning a trimmed response.
-     */
-    private String runShellCommandWithTimeout(String command, long timeoutInSecond)
-            throws TimeoutException {
-        AtomicReference<Exception> exception = new AtomicReference<>(null);
-        AtomicReference<String> result = new AtomicReference<>(null);
-
-        CountDownLatch latch = new CountDownLatch(1);
-
-        new Thread(() -> {
-            try {
-                result.set(ShellHelper.runShellCommandRaw(command));
-            } catch (Exception e) {
-                exception.set(e);
-            } finally {
-                latch.countDown();
-            }
-        }).start();
-
-        try {
-            if (!latch.await(timeoutInSecond, TimeUnit.SECONDS)) {
-                throw new TimeoutException("Command: '" + command + "' could not run in "
-                        + timeoutInSecond + " seconds");
-            }
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt();
-        }
-
-        if (exception.get() != null) {
-            Log.e(TAG, "Command: '" + command + "' failed.", exception.get());
-            throw new RuntimeException(exception.get());
-        }
-
-        return result.get();
-    }
 }
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java b/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
index 7b52576..a35899a 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
@@ -24,6 +24,10 @@
 import androidx.test.InstrumentationRegistry;
 
 import java.io.FileInputStream;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Provides Shell-based utilities such as running a command.
@@ -31,6 +35,43 @@
 public final class ShellHelper {
 
     /**
+     * Runs a Shell command with a timeout, returning a trimmed response.
+     */
+    @NonNull
+    public static String runShellCommandWithTimeout(@NonNull String command, long timeoutInSecond)
+            throws TimeoutException {
+        AtomicReference<Exception> exception = new AtomicReference<>(null);
+        AtomicReference<String> result = new AtomicReference<>(null);
+
+        CountDownLatch latch = new CountDownLatch(1);
+
+        new Thread(() -> {
+            try {
+                result.set(runShellCommandRaw(command));
+            } catch (Exception e) {
+                exception.set(e);
+            } finally {
+                latch.countDown();
+            }
+        }).start();
+
+        try {
+            if (!latch.await(timeoutInSecond, TimeUnit.SECONDS)) {
+                throw new TimeoutException("Command: '" + command + "' could not run in "
+                        + timeoutInSecond + " seconds");
+            }
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+
+        if (exception.get() != null) {
+            throw new AndroidRuntimeException(exception.get());
+        }
+
+        return result.get();
+    }
+
+    /**
      * Runs a Shell command, returning a trimmed response.
      */
     @NonNull