1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tradefed.util; 18 19 import com.android.annotations.Nullable; 20 import com.android.tradefed.command.CommandScheduler; 21 22 import java.io.File; 23 import java.io.IOException; 24 import java.io.OutputStream; 25 import java.util.List; 26 27 /** 28 * Interface for running timed operations and system commands. 29 */ 30 public interface IRunUtil { 31 32 /** 33 * An interface for asynchronously executing an operation that returns a boolean status. 34 */ 35 public static interface IRunnableResult { 36 /** 37 * Execute the operation. 38 * 39 * @return <code>true</code> if operation is performed successfully, <code>false</code> 40 * otherwise 41 * @throws Exception if operation terminated abnormally 42 */ run()43 public boolean run() throws Exception; 44 45 /** 46 * Cancel the operation. 47 */ cancel()48 public void cancel(); 49 50 /** Returns the command associated with the runnable. */ getCommand()51 public default List<String> getCommand() { 52 return null; 53 } 54 } 55 56 /** 57 * Sets the working directory for system commands. 58 * 59 * @param dir the working directory 60 * 61 * @see ProcessBuilder#directory(File) 62 */ setWorkingDir(File dir)63 public void setWorkingDir(File dir); 64 65 /** 66 * Sets a environment variable to be used when running system commands. 67 * 68 * @param key the variable name 69 * @param value the variable value 70 * 71 * @see ProcessBuilder#environment() 72 * 73 */ setEnvVariable(String key, String value)74 public void setEnvVariable(String key, String value); 75 76 /** 77 * Unsets an environment variable, so the system commands run without this environment variable. 78 * 79 * @param key the variable name 80 * 81 * @see ProcessBuilder#environment() 82 */ unsetEnvVariable(String key)83 public void unsetEnvVariable(String key); 84 85 /** 86 * Set the standard error stream to redirect to the standard output stream when running system 87 * commands. Initial value is false. 88 * 89 * @param redirect new value for whether or not to redirect 90 * @see ProcessBuilder#redirectErrorStream(boolean) 91 */ setRedirectStderrToStdout(boolean redirect)92 public void setRedirectStderrToStdout(boolean redirect); 93 94 /** 95 * Helper method to execute a system command, and aborting if it takes longer than a specified 96 * time. 97 * 98 * @param timeout maximum time to wait in ms. 0 means no timeout. 99 * @param command the specified system command and optionally arguments to exec 100 * @return a {@link CommandResult} containing result from command run 101 */ runTimedCmd(final long timeout, final String... command)102 public CommandResult runTimedCmd(final long timeout, final String... command); 103 104 /** 105 * Helper method to execute a system command, abort if it takes longer than a specified time, 106 * and redirect output to files if specified. When {@link OutputStream} are provided this way, 107 * they will be left open at the end of the function. 108 * 109 * @param timeout timeout maximum time to wait in ms. 0 means no timeout. 110 * @param stdout {@link OutputStream} where the std output will be redirected. Can be null. 111 * @param stderr {@link OutputStream} where the error output will be redirected. Can be null. 112 * @param command the specified system command and optionally arguments to exec 113 * @return a {@link CommandResult} containing result from command run 114 */ runTimedCmd( final long timeout, OutputStream stdout, OutputStream stderr, final String... command)115 public CommandResult runTimedCmd( 116 final long timeout, OutputStream stdout, OutputStream stderr, final String... command); 117 118 /** 119 * Helper method to execute a system command, and aborting if it takes longer than a specified 120 * time. 121 * 122 * @param timeout maximum time to wait in ms for each attempt 123 * @param command the specified system command and optionally arguments to exec 124 * @param retryInterval time to wait between command retries 125 * @param attempts the maximum number of attempts to try 126 * @return a {@link CommandResult} containing result from command run 127 */ runTimedCmdRetry(final long timeout, long retryInterval, int attempts, final String... command)128 public CommandResult runTimedCmdRetry(final long timeout, long retryInterval, 129 int attempts, final String... command); 130 131 /** 132 * Helper method to execute a system command, and aborting if it takes longer than a specified 133 * time. Similar to {@link #runTimedCmd(long, String...)}, but does not log any errors on 134 * exception. 135 * 136 * @param timeout maximum time to wait in ms 137 * @param command the specified system command and optionally arguments to exec 138 * @return a {@link CommandResult} containing result from command run 139 */ runTimedCmdSilently(final long timeout, final String... command)140 public CommandResult runTimedCmdSilently(final long timeout, final String... command); 141 142 /** 143 * Helper method to execute a system command, and aborting if it takes longer than a specified 144 * time. Similar to {@link #runTimedCmdRetry(long, long, int, String[])}, 145 * but does not log any errors on exception. 146 * 147 * @param timeout maximum time to wait in ms 148 * @param command the specified system command and optionally arguments to exec 149 * @param retryInterval time to wait between command retries 150 * @param attempts the maximum number of attempts to try 151 * @return a {@link CommandResult} containing result from command run 152 */ runTimedCmdSilentlyRetry(final long timeout, long retryInterval, int attempts, final String... command)153 public CommandResult runTimedCmdSilentlyRetry(final long timeout, long retryInterval, 154 int attempts, final String... command); 155 156 /** 157 * Helper method to execute a system command that requires stdin input, and aborting if it 158 * takes longer than a specified time. 159 * 160 * @param timeout maximum time to wait in ms 161 * @param input the stdin input to pass to process 162 * @param command the specified system command and optionally arguments to exec 163 * @return a {@link CommandResult} containing result from command run 164 */ runTimedCmdWithInput(long timeout, String input, String... command)165 CommandResult runTimedCmdWithInput(long timeout, String input, String... command); 166 167 /** 168 * Helper method to execute a system command that requires stdin input, and aborting if it 169 * takes longer than a specified time. 170 * 171 * @param timeout maximum time to wait in ms 172 * @param input the stdin input to pass to process 173 * @param command {@link List} containing the system command and optionally arguments to exec 174 * @return a {@link CommandResult} containing result from command run 175 */ runTimedCmdWithInput(long timeout, String input, List<String> command)176 CommandResult runTimedCmdWithInput(long timeout, String input, List<String> command); 177 178 /** 179 * Helper method to execute a system command that requires redirecting Stdin from a file, and 180 * aborting if it takes longer than a specified time. 181 * 182 * @param timeout maximum time to wait in ms 183 * @param inputRedirect the {@link File} to redirect as standard input using {@link 184 * ProcessBuilder#redirectInput()}. If null, stdin won't be redirected. 185 * @param command the specified system command and optionally arguments to exec 186 * @return a {@link CommandResult} containing result from command run 187 */ runTimedCmdWithInputRedirect( long timeout, @Nullable File inputRedirect, String... command)188 CommandResult runTimedCmdWithInputRedirect( 189 long timeout, @Nullable File inputRedirect, String... command); 190 191 /** 192 * Helper method to execute a system command asynchronously. 193 * 194 * <p>Will return immediately after launching command. 195 * 196 * @param command the specified system command and optionally arguments to exec 197 * @return the {@link Process} of the executed command 198 * @throws IOException if command failed to run 199 */ runCmdInBackground(String... command)200 public Process runCmdInBackground(String... command) throws IOException; 201 202 /** 203 * An alternate {@link #runCmdInBackground(String...)} method that accepts the command arguments 204 * in {@link List} form. 205 * 206 * @param command the {@link List} containing specified system command and optionally arguments 207 * to exec 208 * @return the {@link Process} of the executed command 209 * @throws IOException if command failed to run 210 */ runCmdInBackground(List<String> command)211 public Process runCmdInBackground(List<String> command) throws IOException; 212 213 /** 214 * Running command with a {@link OutputStream} log the output of the command. 215 * Stdout and stderr are merged together. 216 * @param command the command to run 217 * @param output the OutputStream to save the output 218 * @return the {@link Process} running the command 219 * @throws IOException 220 */ runCmdInBackground(List<String> command, OutputStream output)221 public Process runCmdInBackground(List<String> command, OutputStream output) 222 throws IOException; 223 224 /** 225 * Block and executes an operation, aborting if it takes longer than a specified time. 226 * 227 * @param timeout maximum time to wait in ms 228 * @param runnable {@link IRunUtil.IRunnableResult} to execute 229 * @param logErrors log errors on exception or not. 230 * @return the {@link CommandStatus} result of operation. 231 */ runTimed(long timeout, IRunUtil.IRunnableResult runnable, boolean logErrors)232 public CommandStatus runTimed(long timeout, IRunUtil.IRunnableResult runnable, 233 boolean logErrors); 234 235 /** 236 * Block and executes an operation multiple times until it is successful. 237 * 238 * @param opTimeout maximum time to wait in ms for one operation attempt 239 * @param pollInterval time to wait between command retries 240 * @param attempts the maximum number of attempts to try 241 * @param runnable {@link IRunUtil.IRunnableResult} to execute 242 * @return <code>true</code> if operation completed successfully before attempts reached. 243 */ runTimedRetry(long opTimeout, long pollInterval, int attempts, IRunUtil.IRunnableResult runnable)244 public boolean runTimedRetry(long opTimeout, long pollInterval, int attempts, 245 IRunUtil.IRunnableResult runnable); 246 247 /** 248 * Block and executes an operation multiple times until it is successful. 249 * 250 * @param opTimeout maximum time to wait in ms for a single operation attempt 251 * @param pollInterval initial time to wait between operation attempts 252 * @param maxTime the total approximate maximum time to keep trying the operation 253 * @param runnable {@link IRunUtil.IRunnableResult} to execute 254 * @return <code>true</code> if operation completed successfully before maxTime expired 255 */ runFixedTimedRetry(final long opTimeout, final long pollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)256 public boolean runFixedTimedRetry(final long opTimeout, final long pollInterval, 257 final long maxTime, final IRunUtil.IRunnableResult runnable); 258 259 /** 260 * Block and executes an operation multiple times until it is successful. 261 * <p/> 262 * Exponentially increase the wait time between operation attempts. This is intended to be used 263 * when performing an operation such as polling a server, to give it time to recover in case it 264 * is temporarily down. 265 * 266 * @param opTimeout maximum time to wait in ms for a single operation attempt 267 * @param initialPollInterval initial time to wait between operation attempts 268 * @param maxPollInterval the max time to wait between operation attempts 269 * @param maxTime the total approximate maximum time to keep trying the operation 270 * @param runnable {@link IRunUtil.IRunnableResult} to execute 271 * @return <code>true</code> if operation completed successfully before maxTime expired 272 */ runEscalatingTimedRetry(final long opTimeout, final long initialPollInterval, final long maxPollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)273 public boolean runEscalatingTimedRetry(final long opTimeout, final long initialPollInterval, 274 final long maxPollInterval, final long maxTime, final IRunUtil.IRunnableResult 275 runnable); 276 277 /** 278 * Helper method to sleep for given time, ignoring any exceptions. 279 * 280 * @param time ms to sleep. values less than or equal to 0 will be ignored 281 */ sleep(long time)282 public void sleep(long time); 283 284 /** 285 * Allows/disallows run interrupts on the current thread. If it is allowed, run operations of 286 * the current thread can be interrupted from other threads via {@link #interrupt} method. 287 * 288 * @param allow whether to allow run interrupts on the current thread. 289 */ allowInterrupt(boolean allow)290 public void allowInterrupt(boolean allow); 291 292 /** 293 * Give the interrupt status of the RunUtil. 294 * @return true if the Run can be interrupted, false otherwise. 295 */ isInterruptAllowed()296 public boolean isInterruptAllowed(); 297 298 /** 299 * Set as interruptible after some waiting time. 300 * {@link CommandScheduler#shutdownHard()} to enforce we terminate eventually. 301 * 302 * @param thread the thread that will become interruptible. 303 * @param timeMs time to wait before setting interruptible. 304 */ setInterruptibleInFuture(Thread thread, long timeMs)305 public void setInterruptibleInFuture(Thread thread, long timeMs); 306 307 /** 308 * Interrupts the ongoing/forthcoming run operations on the given thread. The run operations on 309 * the given thread will throw {@link RunInterruptedException}. 310 * 311 * @param thread 312 * @param message the message for {@link RunInterruptedException}. 313 */ interrupt(Thread thread, String message)314 public void interrupt(Thread thread, String message); 315 316 /** 317 * Decide whether or not when creating a process, unsetting environment variable is higher 318 * priority than setting them. 319 * By Default, unsetting is higher priority: meaning if an attempt to set a variable with the 320 * same name is made, it won't happen since the variable will be unset. 321 * Cannot be used on the default {@link IRunUtil} instance. 322 */ setEnvVariablePriority(EnvPriority priority)323 public void setEnvVariablePriority(EnvPriority priority); 324 325 /** 326 * Enum that defines whether setting or unsetting a particular env. variable has priority. 327 */ 328 public enum EnvPriority { 329 SET, 330 UNSET 331 } 332 } 333