Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: build/android/pylib/device/device_utils.py

Issue 895853003: Update from https://crrev.com/314320 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/android/pylib/device/OWNERS ('k') | build/android/pylib/device/device_utils_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 93
94 def _JoinLines(lines): 94 def _JoinLines(lines):
95 # makes sure that the last line is also terminated, and is more memory 95 # makes sure that the last line is also terminated, and is more memory
96 # efficient than first appending an end-line to each line and then joining 96 # efficient than first appending an end-line to each line and then joining
97 # all of them together. 97 # all of them together.
98 return ''.join(s for line in lines for s in (line, '\n')) 98 return ''.join(s for line in lines for s in (line, '\n'))
99 99
100 100
101 class DeviceUtils(object): 101 class DeviceUtils(object):
102 102
103 _MAX_ADB_COMMAND_LENGTH = 512
103 _VALID_SHELL_VARIABLE = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$') 104 _VALID_SHELL_VARIABLE = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
104 105
105 def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT, 106 def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT,
106 default_retries=_DEFAULT_RETRIES): 107 default_retries=_DEFAULT_RETRIES):
107 """DeviceUtils constructor. 108 """DeviceUtils constructor.
108 109
109 Args: 110 Args:
110 device: Either a device serial, an existing AdbWrapper instance, or an 111 device: Either a device serial, an existing AdbWrapper instance, or an
111 an existing AndroidCommands instance. 112 an existing AndroidCommands instance.
112 default_timeout: An integer containing the default number of seconds to 113 default_timeout: An integer containing the default number of seconds to
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 more lines. 455 more lines.
455 CommandTimeoutError on timeout. 456 CommandTimeoutError on timeout.
456 DeviceUnreachableError on missing device. 457 DeviceUnreachableError on missing device.
457 """ 458 """
458 def env_quote(key, value): 459 def env_quote(key, value):
459 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key): 460 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key):
460 raise KeyError('Invalid shell variable name %r' % key) 461 raise KeyError('Invalid shell variable name %r' % key)
461 # using double quotes here to allow interpolation of shell variables 462 # using double quotes here to allow interpolation of shell variables
462 return '%s=%s' % (key, cmd_helper.DoubleQuote(value)) 463 return '%s=%s' % (key, cmd_helper.DoubleQuote(value))
463 464
465 def do_run(cmd):
466 try:
467 return self.adb.Shell(cmd)
468 except device_errors.AdbCommandFailedError as exc:
469 if check_return:
470 raise
471 else:
472 return exc.output
473
464 if not isinstance(cmd, basestring): 474 if not isinstance(cmd, basestring):
465 cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd) 475 cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd)
466 if env: 476 if env:
467 env = ' '.join(env_quote(k, v) for k, v in env.iteritems()) 477 env = ' '.join(env_quote(k, v) for k, v in env.iteritems())
468 cmd = '%s %s' % (env, cmd) 478 cmd = '%s %s' % (env, cmd)
469 if cwd: 479 if cwd:
470 cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd) 480 cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd)
471 if as_root and self.NeedsSU(): 481 if as_root and self.NeedsSU():
472 # "su -c sh -c" allows using shell features in |cmd| 482 # "su -c sh -c" allows using shell features in |cmd|
473 cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd) 483 cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd)
474 if timeout is None: 484 if timeout is None:
475 timeout = self._default_timeout 485 timeout = self._default_timeout
476 486
477 try: 487 if len(cmd) < self._MAX_ADB_COMMAND_LENGTH:
478 output = self.adb.Shell(cmd) 488 output = do_run(cmd)
479 except device_errors.AdbCommandFailedError as e: 489 else:
480 if check_return: 490 with device_temp_file.DeviceTempFile(self.adb, suffix='.sh') as script:
481 raise 491 self._WriteFileWithPush(script.name, cmd)
482 else: 492 logging.info('Large shell command will be run from file: %s ...',
483 output = e.output 493 cmd[:100])
494 output = do_run('sh %s' % script.name_quoted)
484 495
485 output = output.splitlines() 496 output = output.splitlines()
486 if single_line: 497 if single_line:
487 if not output: 498 if not output:
488 return '' 499 return ''
489 elif len(output) == 1: 500 elif len(output) == 1:
490 return output[0] 501 return output[0]
491 else: 502 else:
492 msg = 'one line of output was expected, but got: %s' 503 msg = 'one line of output was expected, but got: %s'
493 raise device_errors.CommandFailedError(msg % output, str(self)) 504 raise device_errors.CommandFailedError(msg % output, str(self))
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 extras=None, timeout=None, retries=None): 580 extras=None, timeout=None, retries=None):
570 if extras is None: 581 if extras is None:
571 extras = {} 582 extras = {}
572 583
573 cmd = ['am', 'instrument'] 584 cmd = ['am', 'instrument']
574 if finish: 585 if finish:
575 cmd.append('-w') 586 cmd.append('-w')
576 if raw: 587 if raw:
577 cmd.append('-r') 588 cmd.append('-r')
578 for k, v in extras.iteritems(): 589 for k, v in extras.iteritems():
579 cmd.extend(['-e', k, v]) 590 cmd.extend(['-e', str(k), str(v)])
580 cmd.append(component) 591 cmd.append(component)
581 return self.RunShellCommand(cmd, check_return=True) 592 return self.RunShellCommand(cmd, check_return=True)
582 593
583 @decorators.WithTimeoutAndRetriesFromInstance() 594 @decorators.WithTimeoutAndRetriesFromInstance()
584 def BroadcastIntent(self, intent_obj, timeout=None, retries=None): 595 def BroadcastIntent(self, intent_obj, timeout=None, retries=None):
585 """Send a broadcast intent. 596 """Send a broadcast intent.
586 597
587 Args: 598 Args:
588 intent: An Intent to broadcast. 599 intent: An Intent to broadcast.
589 timeout: timeout in seconds 600 timeout: timeout in seconds
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 all lines will be terminated. 919 all lines will be terminated.
909 920
910 Raises: 921 Raises:
911 AdbCommandFailedError if the file can't be read. 922 AdbCommandFailedError if the file can't be read.
912 CommandTimeoutError on timeout. 923 CommandTimeoutError on timeout.
913 DeviceUnreachableError on missing device. 924 DeviceUnreachableError on missing device.
914 """ 925 """
915 return _JoinLines(self.RunShellCommand( 926 return _JoinLines(self.RunShellCommand(
916 ['cat', device_path], as_root=as_root, check_return=True)) 927 ['cat', device_path], as_root=as_root, check_return=True))
917 928
929 def _WriteFileWithPush(self, device_path, contents):
930 with tempfile.NamedTemporaryFile() as host_temp:
931 host_temp.write(contents)
932 host_temp.flush()
933 self.adb.Push(host_temp.name, device_path)
934
918 @decorators.WithTimeoutAndRetriesFromInstance() 935 @decorators.WithTimeoutAndRetriesFromInstance()
919 def WriteFile(self, device_path, contents, as_root=False, force_push=False, 936 def WriteFile(self, device_path, contents, as_root=False, force_push=False,
920 timeout=None, retries=None): 937 timeout=None, retries=None):
921 """Writes |contents| to a file on the device. 938 """Writes |contents| to a file on the device.
922 939
923 Args: 940 Args:
924 device_path: A string containing the absolute path to the file to write 941 device_path: A string containing the absolute path to the file to write
925 on the device. 942 on the device.
926 contents: A string containing the data to write to the device. 943 contents: A string containing the data to write to the device.
927 as_root: A boolean indicating whether the write should be executed with 944 as_root: A boolean indicating whether the write should be executed with
928 root privileges (if available). 945 root privileges (if available).
929 force_push: A boolean indicating whether to force the operation to be 946 force_push: A boolean indicating whether to force the operation to be
930 performed by pushing a file to the device. The default is, when the 947 performed by pushing a file to the device. The default is, when the
931 contents are short, to pass the contents using a shell script instead. 948 contents are short, to pass the contents using a shell script instead.
932 timeout: timeout in seconds 949 timeout: timeout in seconds
933 retries: number of retries 950 retries: number of retries
934 951
935 Raises: 952 Raises:
936 CommandFailedError if the file could not be written on the device. 953 CommandFailedError if the file could not be written on the device.
937 CommandTimeoutError on timeout. 954 CommandTimeoutError on timeout.
938 DeviceUnreachableError on missing device. 955 DeviceUnreachableError on missing device.
939 """ 956 """
940 if len(contents) < 512 and not force_push: 957 if not force_push and len(contents) < self._MAX_ADB_COMMAND_LENGTH:
958 # If the contents are small, for efficieny we write the contents with
959 # a shell command rather than pushing a file.
941 cmd = 'echo -n %s > %s' % (cmd_helper.SingleQuote(contents), 960 cmd = 'echo -n %s > %s' % (cmd_helper.SingleQuote(contents),
942 cmd_helper.SingleQuote(device_path)) 961 cmd_helper.SingleQuote(device_path))
943 self.RunShellCommand(cmd, as_root=as_root, check_return=True) 962 self.RunShellCommand(cmd, as_root=as_root, check_return=True)
963 elif as_root and self.NeedsSU():
964 # Adb does not allow to "push with su", so we first push to a temp file
965 # on a safe location, and then copy it to the desired location with su.
966 with device_temp_file.DeviceTempFile(self.adb) as device_temp:
967 self._WriteFileWithPush(device_temp.name, contents)
968 # Here we need 'cp' rather than 'mv' because the temp and
969 # destination files might be on different file systems (e.g.
970 # on internal storage and an external sd card).
971 self.RunShellCommand(['cp', device_temp.name, device_path],
972 as_root=True, check_return=True)
944 else: 973 else:
945 with tempfile.NamedTemporaryFile() as host_temp: 974 # If root is not needed, we can push directly to the desired location.
946 host_temp.write(contents) 975 self._WriteFileWithPush(device_path, contents)
947 host_temp.flush()
948 if as_root and self.NeedsSU():
949 with device_temp_file.DeviceTempFile(self.adb) as device_temp:
950 self.adb.Push(host_temp.name, device_temp.name)
951 # Here we need 'cp' rather than 'mv' because the temp and
952 # destination files might be on different file systems (e.g.
953 # on internal storage and an external sd card)
954 self.RunShellCommand(['cp', device_temp.name, device_path],
955 as_root=True, check_return=True)
956 else:
957 self.adb.Push(host_temp.name, device_path)
958 976
959 @decorators.WithTimeoutAndRetriesFromInstance() 977 @decorators.WithTimeoutAndRetriesFromInstance()
960 def Ls(self, device_path, timeout=None, retries=None): 978 def Ls(self, device_path, timeout=None, retries=None):
961 """Lists the contents of a directory on the device. 979 """Lists the contents of a directory on the device.
962 980
963 Args: 981 Args:
964 device_path: A string containing the path of the directory on the device 982 device_path: A string containing the path of the directory on the device
965 to list. 983 to list.
966 timeout: timeout in seconds 984 timeout: timeout in seconds
967 retries: number of retries 985 retries: number of retries
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
1291 Returns: 1309 Returns:
1292 A Parallelizer operating over |devices|. 1310 A Parallelizer operating over |devices|.
1293 """ 1311 """
1294 if not devices: 1312 if not devices:
1295 devices = adb_wrapper.AdbWrapper.GetDevices() 1313 devices = adb_wrapper.AdbWrapper.GetDevices()
1296 devices = [d if isinstance(d, cls) else cls(d) for d in devices] 1314 devices = [d if isinstance(d, cls) else cls(d) for d in devices]
1297 if async: 1315 if async:
1298 return parallelizer.Parallelizer(devices) 1316 return parallelizer.Parallelizer(devices)
1299 else: 1317 else:
1300 return parallelizer.SyncParallelizer(devices) 1318 return parallelizer.SyncParallelizer(devices)
OLDNEW
« no previous file with comments | « build/android/pylib/device/OWNERS ('k') | build/android/pylib/device/device_utils_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698