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.result.error.ErrorIdentifier; 21 22 import java.io.File; 23 import java.io.IOException; 24 import java.io.OutputStream; 25 import java.lang.ProcessBuilder.Redirect; 26 import java.util.List; 27 28 /** 29 * Interface for running timed operations and system commands. 30 */ 31 public interface IRunUtil { 32 33 /** 34 * An interface for asynchronously executing an operation that returns a boolean status. 35 */ 36 public static interface IRunnableResult { 37 /** 38 * Execute the operation. 39 * 40 * @return <code>true</code> if operation is performed successfully, <code>false</code> 41 * otherwise 42 * @throws Exception if operation terminated abnormally 43 */ run()44 public boolean run() throws Exception; 45 46 /** 47 * Cancel the operation. 48 */ cancel()49 public void cancel(); 50 51 /** Returns the command associated with the runnable. */ getCommand()52 public default List<String> getCommand() { 53 return null; 54 } 55 56 /** Returns the {@link CommandResult} associated with the command. */ getResult()57 public default CommandResult getResult() { 58 return null; 59 } 60 61 /** 62 * Checks if the currently running operation has made progress since the last check. 63 * 64 * @param idleOutputTimeout ms idle with no observed progress before beginning to assume no 65 * progress is being made. 66 * @return true if progress has been detected otherwise false. 67 */ checkOutputMonitor(Long idleOutputTimeout)68 public default boolean checkOutputMonitor(Long idleOutputTimeout) { 69 // Allow existing implementations not to implement this method. 70 throw new UnsupportedOperationException("checkOutputMonitor() has no implementation."); 71 } 72 } 73 74 /** 75 * Sets the working directory for system commands. 76 * 77 * @param dir the working directory 78 * 79 * @see ProcessBuilder#directory(File) 80 */ setWorkingDir(File dir)81 public void setWorkingDir(File dir); 82 83 /** 84 * Sets a environment variable to be used when running system commands. 85 * 86 * @param key the variable name 87 * @param value the variable value 88 * 89 * @see ProcessBuilder#environment() 90 * 91 */ setEnvVariable(String key, String value)92 public void setEnvVariable(String key, String value); 93 94 /** 95 * Unsets an environment variable, so the system commands run without this environment variable. 96 * 97 * @param key the variable name 98 * 99 * @see ProcessBuilder#environment() 100 */ unsetEnvVariable(String key)101 public void unsetEnvVariable(String key); 102 103 /** 104 * Set the standard error stream to redirect to the standard output stream when running system 105 * commands. Initial value is false. 106 * 107 * @param redirect new value for whether or not to redirect 108 * @see ProcessBuilder#redirectErrorStream(boolean) 109 */ setRedirectStderrToStdout(boolean redirect)110 public void setRedirectStderrToStdout(boolean redirect); 111 112 /** 113 * Helper method to execute a system command, and aborting if it takes longer than a specified 114 * time. 115 * 116 * @param timeout maximum time to wait in ms. 0 means no timeout. 117 * @param command the specified system command and optionally arguments to exec 118 * @return a {@link CommandResult} containing result from command run 119 */ runTimedCmd(final long timeout, final String... command)120 public CommandResult runTimedCmd(final long timeout, final String... command); 121 122 /** 123 * Helper method to execute a system command, and aborting if it takes longer than a specified 124 * time. Also monitors the output streams for activity, aborting if no stream activity is 125 * observed for a specified time. If the idleOutputTimeout is set to zero, no stream monitoring 126 * will occur. 127 * 128 * @param timeout maximum time to wait in ms. 0 means no timeout. 129 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 130 * @param command the specified system command and optionally arguments to exec 131 * @return a {@link CommandResult} containing result from command run 132 */ runTimedCmdWithOutputMonitor( final long timeout, final long idleOutputTimeout, final String... command)133 public CommandResult runTimedCmdWithOutputMonitor( 134 final long timeout, final long idleOutputTimeout, final String... command); 135 136 /** 137 * Helper method to execute a system command, abort if it takes longer than a specified time, 138 * and redirect output to files if specified. When {@link OutputStream} are provided this way, 139 * they will be left open at the end of the function. 140 * 141 * @param timeout timeout maximum time to wait in ms. 0 means no timeout. 142 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 143 * @param stdout {@link OutputStream} where the std output will be redirected. Can be null. 144 * @param stderr {@link OutputStream} where the error output will be redirected. Can be null. 145 * @param command the specified system command and optionally arguments to exec 146 * @return a {@link CommandResult} containing result from command run 147 */ runTimedCmdWithOutputMonitor( final long timeout, final long idleOutputTimeout, OutputStream stdout, OutputStream stderr, final String... command)148 public CommandResult runTimedCmdWithOutputMonitor( 149 final long timeout, 150 final long idleOutputTimeout, 151 OutputStream stdout, 152 OutputStream stderr, 153 final String... command); 154 155 /** 156 * Helper method to execute a system command, abort if it takes longer than a specified time, 157 * and redirect output to files if specified. When {@link OutputStream} are provided this way, 158 * they will be left open at the end of the function. 159 * 160 * @param timeout timeout maximum time to wait in ms. 0 means no timeout. 161 * @param stdout {@link OutputStream} where the std output will be redirected. Can be null. 162 * @param stderr {@link OutputStream} where the error output will be redirected. Can be null. 163 * @param command the specified system command and optionally arguments to exec 164 * @return a {@link CommandResult} containing result from command run 165 */ runTimedCmd( final long timeout, OutputStream stdout, OutputStream stderr, final String... command)166 public CommandResult runTimedCmd( 167 final long timeout, OutputStream stdout, OutputStream stderr, final String... command); 168 169 /** 170 * Helper method to execute a system command, and aborting if it takes longer than a specified 171 * time. 172 * 173 * @param timeout maximum time to wait in ms for each attempt 174 * @param command the specified system command and optionally arguments to exec 175 * @param retryInterval time to wait between command retries 176 * @param attempts the maximum number of attempts to try 177 * @return a {@link CommandResult} containing result from command run 178 */ runTimedCmdRetry(final long timeout, long retryInterval, int attempts, final String... command)179 public CommandResult runTimedCmdRetry(final long timeout, long retryInterval, 180 int attempts, final String... command); 181 182 /** 183 * Helper method to execute a system command, and aborting if it takes longer than a specified 184 * time. Also monitors the output streams for activity, aborting if no stream activity is 185 * observed for a specified time. If the idleOutputTimeout is set to zero, no stream monitoring 186 * will occur. 187 * 188 * @param timeout maximum time to wait in ms for each attempt 189 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 190 * @param command the specified system command and optionally arguments to exec 191 * @param retryInterval time to wait between command retries 192 * @param attempts the maximum number of attempts to try 193 * @return a {@link CommandResult} containing result from command run 194 */ runTimedCmdRetryWithOutputMonitor( final long timeout, final long idleOutputTimeout, long retryInterval, int attempts, final String... command)195 public CommandResult runTimedCmdRetryWithOutputMonitor( 196 final long timeout, 197 final long idleOutputTimeout, 198 long retryInterval, 199 int attempts, 200 final String... command); 201 202 /** 203 * Helper method to execute a system command, and aborting if it takes longer than a specified 204 * time. Similar to {@link #runTimedCmd(long, String...)}, but does not log any errors on 205 * exception. 206 * 207 * @param timeout maximum time to wait in ms 208 * @param command the specified system command and optionally arguments to exec 209 * @return a {@link CommandResult} containing result from command run 210 */ runTimedCmdSilently(final long timeout, final String... command)211 public CommandResult runTimedCmdSilently(final long timeout, final String... command); 212 213 /** 214 * Helper method to execute a system command, and aborting if it takes longer than a specified 215 * time. Similar to {@link #runTimedCmdRetry(long, long, int, String[])}, 216 * but does not log any errors on exception. 217 * 218 * @param timeout maximum time to wait in ms 219 * @param command the specified system command and optionally arguments to exec 220 * @param retryInterval time to wait between command retries 221 * @param attempts the maximum number of attempts to try 222 * @return a {@link CommandResult} containing result from command run 223 */ runTimedCmdSilentlyRetry(final long timeout, long retryInterval, int attempts, final String... command)224 public CommandResult runTimedCmdSilentlyRetry(final long timeout, long retryInterval, 225 int attempts, final String... command); 226 227 /** 228 * Helper method to execute a system command that requires stdin input, and aborting if it 229 * takes longer than a specified time. 230 * 231 * @param timeout maximum time to wait in ms 232 * @param input the stdin input to pass to process 233 * @param command the specified system command and optionally arguments to exec 234 * @return a {@link CommandResult} containing result from command run 235 */ runTimedCmdWithInput(long timeout, String input, String... command)236 CommandResult runTimedCmdWithInput(long timeout, String input, String... command); 237 238 /** 239 * Helper method to execute a system command that requires stdin input, and aborting if it 240 * takes longer than a specified time. 241 * 242 * @param timeout maximum time to wait in ms 243 * @param input the stdin input to pass to process 244 * @param command {@link List} containing the system command and optionally arguments to exec 245 * @return a {@link CommandResult} containing result from command run 246 */ runTimedCmdWithInput(long timeout, String input, List<String> command)247 CommandResult runTimedCmdWithInput(long timeout, String input, List<String> command); 248 249 /** 250 * Helper method to execute a system command, abort if it takes longer than a specified time, 251 * and redirect output to files if specified. 252 * 253 * @param timeout timeout maximum time to wait in ms. 0 means no timeout. 254 * @param input the stdin input to pass to process 255 * @param command the specified system command and optionally arguments to exec 256 * @param stdoutFile {@link File} where the std output will be redirected. Can be null. 257 * @param stderrFile {@link File} where the error output will be redirected. Can be null. 258 * @return a {@link CommandResult} containing result from command run 259 */ runTimedCmdWithInput( long timeout, String input, File stdoutFile, File stderrFile, final String... command)260 public CommandResult runTimedCmdWithInput( 261 long timeout, String input, File stdoutFile, File stderrFile, final String... command); 262 263 /** 264 * Helper method to execute a system command that requires redirecting Stdin from a file, and 265 * aborting if it takes longer than a specified time. 266 * 267 * @param timeout maximum time to wait in ms 268 * @param inputRedirect the {@link File} to redirect as standard input using {@link 269 * ProcessBuilder#redirectInput()}. If null, stdin won't be redirected. 270 * @param command the specified system command and optionally arguments to exec 271 * @return a {@link CommandResult} containing result from command run 272 */ runTimedCmdWithInputRedirect( long timeout, @Nullable File inputRedirect, String... command)273 CommandResult runTimedCmdWithInputRedirect( 274 long timeout, @Nullable File inputRedirect, String... command); 275 276 /** 277 * Helper method to execute a system command asynchronously. 278 * 279 * <p>Will return immediately after launching command. 280 * 281 * @param command the specified system command and optionally arguments to exec 282 * @return the {@link Process} of the executed command 283 * @throws IOException if command failed to run 284 */ runCmdInBackground(String... command)285 public Process runCmdInBackground(String... command) throws IOException; 286 287 /** 288 * Helper method to execute a system command asynchronously. 289 * 290 * <p>Will return immediately after launching command. 291 * 292 * @param redirect The {@link Redirect} to apply to the {@link ProcessBuilder}. 293 * @param command the specified system command and optionally arguments to exec 294 * @return the {@link Process} of the executed command 295 * @throws IOException if command failed to run 296 */ runCmdInBackground(Redirect redirect, final String... command)297 public Process runCmdInBackground(Redirect redirect, final String... command) 298 throws IOException; 299 300 /** 301 * An alternate {@link #runCmdInBackground(String...)} method that accepts the command arguments 302 * in {@link List} form. 303 * 304 * @param command the {@link List} containing specified system command and optionally arguments 305 * to exec 306 * @return the {@link Process} of the executed command 307 * @throws IOException if command failed to run 308 */ runCmdInBackground(List<String> command)309 public Process runCmdInBackground(List<String> command) throws IOException; 310 311 /** 312 * An alternate {@link #runCmdInBackground(String...)} method that accepts the command arguments 313 * in {@link List} form. 314 * 315 * @param redirect The {@link Redirect} to apply to the {@link ProcessBuilder}. 316 * @param command the {@link List} containing specified system command and optionally arguments 317 * to exec 318 * @return the {@link Process} of the executed command 319 * @throws IOException if command failed to run 320 */ runCmdInBackground(Redirect redirect, List<String> command)321 public Process runCmdInBackground(Redirect redirect, List<String> command) throws IOException; 322 323 /** 324 * Running command with a {@link OutputStream} log the output of the command. 325 * Stdout and stderr are merged together. 326 * @param command the command to run 327 * @param output the OutputStream to save the output 328 * @return the {@link Process} running the command 329 * @throws IOException 330 */ runCmdInBackground(List<String> command, OutputStream output)331 public Process runCmdInBackground(List<String> command, OutputStream output) 332 throws IOException; 333 334 /** 335 * Block and executes an operation, aborting if it takes longer than a specified time. 336 * 337 * @param timeout maximum time to wait in ms 338 * @param runnable {@link IRunUtil.IRunnableResult} to execute 339 * @param logErrors log errors on exception or not. 340 * @return the {@link CommandStatus} result of operation. 341 */ runTimed(long timeout, IRunUtil.IRunnableResult runnable, boolean logErrors)342 public CommandStatus runTimed(long timeout, IRunUtil.IRunnableResult runnable, 343 boolean logErrors); 344 345 /** 346 * Block and executes an operation, aborting if it takes longer than a specified time. Also 347 * monitors the output streams for activity, aborting if no stream activity is observed for a 348 * specified time. If the idleOutputTimeout is set to zero, no stream monitoring will occur. 349 * 350 * @param timeout maximum time to wait in ms 351 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 352 * @param runnable {@link IRunUtil.IRunnableResult} to execute 353 * @param logErrors log errors on exception or not. 354 * @return the {@link CommandStatus} result of operation. 355 */ runTimedWithOutputMonitor( final long timeout, final long idleOutputTimeout, IRunUtil.IRunnableResult runnable, boolean logErrors)356 public CommandStatus runTimedWithOutputMonitor( 357 final long timeout, 358 final long idleOutputTimeout, 359 IRunUtil.IRunnableResult runnable, 360 boolean logErrors); 361 362 /** 363 * Block and executes an operation multiple times until it is successful. 364 * 365 * @param opTimeout maximum time to wait in ms for one operation attempt 366 * @param pollInterval time to wait between command retries 367 * @param attempts the maximum number of attempts to try 368 * @param runnable {@link IRunUtil.IRunnableResult} to execute 369 * @return <code>true</code> if operation completed successfully before attempts reached. 370 */ runTimedRetry(long opTimeout, long pollInterval, int attempts, IRunUtil.IRunnableResult runnable)371 public boolean runTimedRetry(long opTimeout, long pollInterval, int attempts, 372 IRunUtil.IRunnableResult runnable); 373 374 /** 375 * Block and executes an operation multiple times until it is successful. Also monitors the 376 * output streams for activity, aborting if no stream activity is observed for a specified time. 377 * If the idleOutputTimeout is set to zero, no stream monitoring will occur. 378 * 379 * @param opTimeout maximum time to wait in ms for one operation attempt 380 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 381 * @param pollInterval time to wait between command retries 382 * @param attempts the maximum number of attempts to try 383 * @param runnable {@link IRunUtil.IRunnableResult} to execute 384 * @return <code>true</code> if operation completed successfully before attempts reached. 385 */ runTimedRetryWithOutputMonitor( final long opTimeout, final long idleOutputTimeout, long pollInterval, int attempts, IRunUtil.IRunnableResult runnable)386 public boolean runTimedRetryWithOutputMonitor( 387 final long opTimeout, 388 final long idleOutputTimeout, 389 long pollInterval, 390 int attempts, 391 IRunUtil.IRunnableResult runnable); 392 393 /** 394 * Block and executes an operation multiple times until it is successful. 395 * 396 * @param opTimeout maximum time to wait in ms for a single operation attempt 397 * @param pollInterval initial time to wait between operation attempts 398 * @param maxTime the total approximate maximum time to keep trying the operation 399 * @param runnable {@link IRunUtil.IRunnableResult} to execute 400 * @return <code>true</code> if operation completed successfully before maxTime expired 401 */ runFixedTimedRetry(final long opTimeout, final long pollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)402 public boolean runFixedTimedRetry(final long opTimeout, final long pollInterval, 403 final long maxTime, final IRunUtil.IRunnableResult runnable); 404 405 /** 406 * Block and executes an operation multiple times until it is successful. Also monitors the 407 * output streams for activity, aborting if no stream activity is observed for a specified time. 408 * If the idleOutputTimeout is set to zero, no stream monitoring will occur. 409 * 410 * @param opTimeout maximum time to wait in ms for a single operation attempt 411 * @param idleOutputTimeout maximum time to wait in ms for output on the output streams 412 * @param pollInterval initial time to wait between operation attempts 413 * @param maxTime the total approximate maximum time to keep trying the operation 414 * @param runnable {@link IRunUtil.IRunnableResult} to execute 415 * @return <code>true</code> if operation completed successfully before maxTime expired 416 */ runFixedTimedRetryWithOutputMonitor( final long opTimeout, final long idleOutputTimeout, final long pollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)417 public boolean runFixedTimedRetryWithOutputMonitor( 418 final long opTimeout, 419 final long idleOutputTimeout, 420 final long pollInterval, 421 final long maxTime, 422 final IRunUtil.IRunnableResult runnable); 423 424 /** 425 * Block and executes an operation multiple times until it is successful. 426 * <p/> 427 * Exponentially increase the wait time between operation attempts. This is intended to be used 428 * when performing an operation such as polling a server, to give it time to recover in case it 429 * is temporarily down. 430 * 431 * @param opTimeout maximum time to wait in ms for a single operation attempt 432 * @param initialPollInterval initial time to wait between operation attempts 433 * @param maxPollInterval the max time to wait between operation attempts 434 * @param maxTime the total approximate maximum time to keep trying the operation 435 * @param runnable {@link IRunUtil.IRunnableResult} to execute 436 * @return <code>true</code> if operation completed successfully before maxTime expired 437 */ runEscalatingTimedRetry(final long opTimeout, final long initialPollInterval, final long maxPollInterval, final long maxTime, final IRunUtil.IRunnableResult runnable)438 public boolean runEscalatingTimedRetry(final long opTimeout, final long initialPollInterval, 439 final long maxPollInterval, final long maxTime, final IRunUtil.IRunnableResult 440 runnable); 441 442 /** 443 * Helper method to sleep for given time, ignoring any exceptions. 444 * 445 * @param time ms to sleep. values less than or equal to 0 will be ignored 446 */ sleep(long time)447 public void sleep(long time); 448 449 /** 450 * Allows/disallows run interrupts on the current thread. If it is allowed, run operations of 451 * the current thread can be interrupted from other threads via {@link #interrupt} method. 452 * 453 * @param allow whether to allow run interrupts on the current thread. 454 */ allowInterrupt(boolean allow)455 public void allowInterrupt(boolean allow); 456 457 /** 458 * Give the interrupt status of the RunUtil. 459 * @return true if the Run can be interrupted, false otherwise. 460 */ isInterruptAllowed()461 public boolean isInterruptAllowed(); 462 463 /** 464 * Set as interruptible after some waiting time. 465 * {@link CommandScheduler#shutdownHard()} to enforce we terminate eventually. 466 * 467 * @param thread the thread that will become interruptible. 468 * @param timeMs time to wait before setting interruptible. 469 */ setInterruptibleInFuture(Thread thread, long timeMs)470 public void setInterruptibleInFuture(Thread thread, long timeMs); 471 472 /** 473 * Interrupts the ongoing/forthcoming run operations on the given thread. The run operations on 474 * the given thread will throw {@link RunInterruptedException}. 475 * 476 * @param thread 477 * @param message the message for {@link RunInterruptedException}. 478 */ interrupt(Thread thread, String message)479 public void interrupt(Thread thread, String message); 480 481 /** 482 * Interrupts the ongoing/forthcoming run operations on the given thread. The run operations on 483 * the given thread will throw {@link RunInterruptedException}. 484 * 485 * @param thread 486 * @param message the message for {@link RunInterruptedException}. 487 * @param errorId Representing the cause of the interruption when known. 488 */ interrupt(Thread thread, String message, ErrorIdentifier errorId)489 public void interrupt(Thread thread, String message, ErrorIdentifier errorId); 490 491 /** 492 * Decide whether or not when creating a process, unsetting environment variable is higher 493 * priority than setting them. 494 * By Default, unsetting is higher priority: meaning if an attempt to set a variable with the 495 * same name is made, it won't happen since the variable will be unset. 496 * Cannot be used on the default {@link IRunUtil} instance. 497 */ setEnvVariablePriority(EnvPriority priority)498 public void setEnvVariablePriority(EnvPriority priority); 499 500 /** 501 * Allow to use linux 'kill' interruption on process running through #runTimed methods when it 502 * reaches a timeout. 503 * 504 * Cannot be used on the default {@link IRunUtil} instance. 505 */ setLinuxInterruptProcess(boolean interrupt)506 public void setLinuxInterruptProcess(boolean interrupt); 507 508 /** 509 * Enum that defines whether setting or unsetting a particular env. variable has priority. 510 */ 511 public enum EnvPriority { 512 SET, 513 UNSET 514 } 515 } 516