Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Provides a variety of device interactions based on adb. | 5 """Provides a variety of device interactions based on adb. |
| 6 | 6 |
| 7 Eventually, this will be based on adb_wrapper. | 7 Eventually, this will be based on adb_wrapper. |
| 8 """ | 8 """ |
| 9 # pylint: disable=W0613 | 9 # pylint: disable=W0613 |
| 10 | 10 |
| 11 import signal | |
| 11 import time | 12 import time |
| 12 | 13 |
| 13 import pylib.android_commands | 14 import pylib.android_commands |
| 14 from pylib.device import adb_wrapper | 15 from pylib.device import adb_wrapper |
| 15 from pylib.device import decorators | 16 from pylib.device import decorators |
| 16 from pylib.device import device_errors | 17 from pylib.device import device_errors |
| 17 from pylib.utils import apk_helper | 18 from pylib.utils import apk_helper |
| 18 from pylib.utils import parallelizer | 19 from pylib.utils import parallelizer |
| 19 | 20 |
| 20 _DEFAULT_TIMEOUT = 30 | 21 _DEFAULT_TIMEOUT = 30 |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 out = self.old_interface.Install(apk_path, reinstall=reinstall) | 238 out = self.old_interface.Install(apk_path, reinstall=reinstall) |
| 238 for line in out.splitlines(): | 239 for line in out.splitlines(): |
| 239 if 'Failure' in line: | 240 if 'Failure' in line: |
| 240 raise device_errors.CommandFailedError( | 241 raise device_errors.CommandFailedError( |
| 241 ['adb', 'install', apk_path], line.strip()) | 242 ['adb', 'install', apk_path], line.strip()) |
| 242 except AssertionError as e: | 243 except AssertionError as e: |
| 243 raise device_errors.CommandFailedError( | 244 raise device_errors.CommandFailedError( |
| 244 ['adb', 'install', apk_path], str(e)) | 245 ['adb', 'install', apk_path], str(e)) |
| 245 | 246 |
| 246 @decorators.WithTimeoutAndRetriesFromInstance() | 247 @decorators.WithTimeoutAndRetriesFromInstance() |
| 247 def RunShellCommand(self, cmd, check_return=False, root=False, timeout=None, | 248 def RunShellCommand(self, cmd, check_return=False, as_root=False, |
| 248 retries=None): | 249 timeout=None, retries=None): |
| 249 """Run an ADB shell command. | 250 """Run an ADB shell command. |
| 250 | 251 |
| 251 TODO(jbudorick) Switch the default value of check_return to True after | 252 TODO(jbudorick) Switch the default value of check_return to True after |
| 252 AndroidCommands is gone. | 253 AndroidCommands is gone. |
| 253 | 254 |
| 254 Args: | 255 Args: |
| 255 cmd: A list containing the command to run on the device and any arguments. | 256 cmd: A list containing the command to run on the device and any arguments. |
| 256 check_return: A boolean indicating whether or not the return code should | 257 check_return: A boolean indicating whether or not the return code should |
| 257 be checked. | 258 be checked. |
| 259 as_root: A boolean indicating whether the shell command should be run | |
| 260 with root privileges. | |
| 258 timeout: Same as for |IsOnline|. | 261 timeout: Same as for |IsOnline|. |
| 259 retries: Same as for |IsOnline|. | 262 retries: Same as for |IsOnline|. |
| 260 Raises: | 263 Raises: |
| 261 CommandFailedError if check_return is True and the return code is nozero. | 264 CommandFailedError if check_return is True and the return code is nozero. |
| 262 Returns: | 265 Returns: |
| 263 The output of the command. | 266 The output of the command. |
| 264 """ | 267 """ |
| 265 return self._RunShellCommandImpl(cmd, check_return=check_return, root=root, | 268 return self._RunShellCommandImpl(cmd, check_return=check_return, |
| 266 timeout=timeout) | 269 as_root=as_root, timeout=timeout) |
| 267 | 270 |
| 268 def _RunShellCommandImpl(self, cmd, check_return=False, root=False, | 271 def _RunShellCommandImpl(self, cmd, check_return=False, as_root=False, |
| 269 timeout=None): | 272 timeout=None): |
| 270 """Implementation of RunShellCommand. | 273 """Implementation of RunShellCommand. |
| 271 | 274 |
| 272 This is split from RunShellCommand to allow other DeviceUtils methods to | 275 This is split from RunShellCommand to allow other DeviceUtils methods to |
| 273 call RunShellCommand without spawning a new timeout thread. | 276 call RunShellCommand without spawning a new timeout thread. |
| 274 | 277 |
| 275 TODO(jbudorick) Remove the timeout parameter once this is no longer | 278 TODO(jbudorick) Remove the timeout parameter once this is no longer |
| 276 implemented via AndroidCommands. | 279 implemented via AndroidCommands. |
| 277 | 280 |
| 278 Args: | 281 Args: |
| 279 cmd: Same as for |RunShellCommand|. | 282 cmd: Same as for |RunShellCommand|. |
| 280 check_return: Same as for |RunShellCommand|. | 283 check_return: Same as for |RunShellCommand|. |
| 284 as_root: Same as for |RunShellCommand|. | |
| 281 timeout: Same as for |IsOnline|. | 285 timeout: Same as for |IsOnline|. |
| 282 Raises: | 286 Raises: |
| 283 Same as for |RunShellCommand|. | 287 Same as for |RunShellCommand|. |
| 284 Returns: | 288 Returns: |
| 285 Same as for |RunShellCommand|. | 289 Same as for |RunShellCommand|. |
| 286 """ | 290 """ |
| 287 if isinstance(cmd, list): | 291 if isinstance(cmd, list): |
| 288 cmd = ' '.join(cmd) | 292 cmd = ' '.join(cmd) |
| 289 if root and not self.HasRoot(): | 293 if as_root and not self.HasRoot(): |
| 290 cmd = 'su -c %s' % cmd | 294 cmd = 'su -c %s' % cmd |
| 291 if check_return: | 295 if check_return: |
| 292 code, output = self.old_interface.GetShellCommandStatusAndOutput( | 296 code, output = self.old_interface.GetShellCommandStatusAndOutput( |
| 293 cmd, timeout_time=timeout) | 297 cmd, timeout_time=timeout) |
| 294 if int(code) != 0: | 298 if int(code) != 0: |
| 295 raise device_errors.CommandFailedError( | 299 raise device_errors.CommandFailedError( |
| 296 cmd, 'Nonzero exit code (%d)' % code) | 300 cmd, 'Nonzero exit code (%d)' % code) |
| 297 else: | 301 else: |
| 298 output = self.old_interface.RunShellCommand(cmd, timeout_time=timeout) | 302 output = self.old_interface.RunShellCommand(cmd, timeout_time=timeout) |
| 299 return output | 303 return output |
| 300 | 304 |
| 305 @decorators.WithTimeoutAndRetriesFromInstance() | |
| 306 def KillAll(self, process_name, signum=signal.SIGKILL, as_root=False, | |
| 307 blocking=False, timeout=None, retries=None): | |
| 308 """Kill all processes with the given name on the device. | |
| 309 | |
|
frankf
2014/06/20 00:56:56
Update the docstring to include the exception
jbudorick
2014/06/23 16:44:02
Done.
| |
| 310 Args: | |
| 311 process_name: A string containing the name of the process to kill. | |
| 312 signum: An integer containing the signal number to send to kill. Defaults | |
| 313 to 9 (SIGKILL). | |
| 314 as_root: A boolean indicating whether the kill should be executed with | |
| 315 root priveleges. | |
| 316 blocking: A boolean indicating whether we should wait until all processes | |
| 317 with the given |process_name| are dead. | |
| 318 timeout: Same as for |IsOnline|. | |
| 319 retries: Same as for |IsOnline|. | |
| 320 """ | |
| 321 pids = self.old_interface.ExtractPid(process_name) | |
| 322 if len(pids) == 0: | |
| 323 raise device_errors.CommandFailedError( | |
| 324 ['adb', 'shell', 'kill'], 'No process "%s"' % process_name) | |
|
frankf
2014/06/20 00:56:55
Why does this include such a command list? You hav
jbudorick
2014/06/23 16:44:02
Created a new AdbCommandFailedError that derives f
| |
| 325 | |
| 326 if blocking: | |
| 327 total_killed = self.old_interface.KillAllBlocking( | |
| 328 process_name, signum=signum, with_su=as_root, timeout_sec=timeout) | |
| 329 else: | |
| 330 total_killed = self.old_interface.KillAll( | |
| 331 process_name, signum=signum, with_su=as_root) | |
| 332 if total_killed == 0: | |
| 333 raise device_errors.CommandFailedError( | |
| 334 ['adb', 'shell', 'kill'], 'Failed to kill "%s"' % process_name) | |
| 335 | |
| 336 @decorators.WithTimeoutAndRetriesFromInstance() | |
| 337 def StartActivity(self, intent, blocking=False, trace_file_name=None, | |
| 338 force_stop=False, timeout=None, retries=None): | |
| 339 """Start package's activity on the device. | |
| 340 | |
| 341 Args: | |
| 342 intent: An Intent to send. | |
| 343 blocking: A boolean indicating whether we should wait for the activity to | |
| 344 finish launching. | |
| 345 trace_file_name: If present, a string that both indicates that we want to | |
| 346 profile the activity and contains the path to which the | |
| 347 trace should be saved. | |
| 348 force_stop: A boolean indicating whether we should stop the activity | |
| 349 before starting it. | |
| 350 timeout: Same as for |IsOnline|. | |
| 351 retries: Same as for |IsOnline|. | |
| 352 """ | |
| 353 output = self.old_interface.StartActivity( | |
| 354 intent.package, intent.activity, wait_for_completion=blocking, | |
| 355 action=intent.action, category=intent.category, data=intent.data, | |
| 356 extras=intent.extras, trace_file_name=trace_file_name, | |
| 357 force_stop=force_stop, flags=intent.flags) | |
| 358 for l in output: | |
| 359 if l.startswith('Error:'): | |
| 360 raise device_errors.CommandFailedError( | |
| 361 ['adb', 'shell', 'am', 'start'], l) | |
|
frankf
2014/06/20 00:56:55
same here
jbudorick
2014/06/23 16:44:02
using the reworked CommandFailedError, as describe
| |
| 362 | |
| 363 @decorators.WithTimeoutAndRetriesFromInstance() | |
| 364 def BroadcastIntent(self, intent, timeout=None, retries=None): | |
| 365 """Send a broadcast intent. | |
| 366 | |
| 367 Args: | |
| 368 intent: An Intent to broadcast. | |
| 369 timeout: Same as for |IsOnline|. | |
| 370 retries: Same as for |IsOnline|. | |
| 371 """ | |
| 372 package, old_intent = intent.action.rsplit('.', 1) | |
| 373 if intent.extras is None: | |
| 374 args = [] | |
| 375 else: | |
| 376 args = ['-e %s%s' % (k, ' "%s"' % v if v else '') | |
| 377 for k, v in intent.extras.items() if len(k) > 0] | |
| 378 self.old_interface.BroadcastIntent(package, old_intent, *args) | |
| 379 | |
| 301 def __str__(self): | 380 def __str__(self): |
| 302 """Returns the device serial.""" | 381 """Returns the device serial.""" |
| 303 return self.old_interface.GetDevice() | 382 return self.old_interface.GetDevice() |
| 304 | 383 |
| 305 @staticmethod | 384 @staticmethod |
| 306 def parallel(devices=None, async=False): | 385 def parallel(devices=None, async=False): |
| 307 """Creates a Parallelizer to operate over the provided list of devices. | 386 """Creates a Parallelizer to operate over the provided list of devices. |
| 308 | 387 |
| 309 If |devices| is either |None| or an empty list, the Parallelizer will | 388 If |devices| is either |None| or an empty list, the Parallelizer will |
| 310 operate over all attached devices. | 389 operate over all attached devices. |
| 311 | 390 |
| 312 Args: | 391 Args: |
| 313 devices: A list of either DeviceUtils instances or objects from | 392 devices: A list of either DeviceUtils instances or objects from |
| 314 from which DeviceUtils instances can be constructed. If None, | 393 from which DeviceUtils instances can be constructed. If None, |
| 315 all attached devices will be used. | 394 all attached devices will be used. |
| 316 async: If true, returns a Parallelizer that runs operations | 395 async: If true, returns a Parallelizer that runs operations |
| 317 asynchronously. | 396 asynchronously. |
| 318 Returns: | 397 Returns: |
| 319 A Parallelizer operating over |devices|. | 398 A Parallelizer operating over |devices|. |
| 320 """ | 399 """ |
| 321 if not devices or len(devices) == 0: | 400 if not devices or len(devices) == 0: |
| 322 devices = pylib.android_commands.GetAttachedDevices() | 401 devices = pylib.android_commands.GetAttachedDevices() |
| 323 parallelizer_type = (parallelizer.Parallelizer if async | 402 parallelizer_type = (parallelizer.Parallelizer if async |
| 324 else parallelizer.SyncParallelizer) | 403 else parallelizer.SyncParallelizer) |
| 325 return parallelizer_type([ | 404 return parallelizer_type([ |
| 326 d if isinstance(d, DeviceUtils) else DeviceUtils(d) | 405 d if isinstance(d, DeviceUtils) else DeviceUtils(d) |
| 327 for d in devices]) | 406 for d in devices]) |
| 328 | 407 |
| OLD | NEW |